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

test_ppg.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  * A very simple push initiator for testing a push proxy gateway
00059  *
00060  * Read pap control content and push content from files, pack them into a PAP
00061  * protocol MIME message and invoke push services specified by an url. Use a 
00062  * hardcoded message boundary (asdlfkjiurwgasf), for simpler command line 
00063  * interface.
00064  * Repetitions and use of multiple threads can be requested, in addition of 
00065  * setting of some headers. 
00066  *
00067  * By Aarno Syvänen for Wiral Ltd and Global Networks Inc.
00068  */
00069 
00070 #define MAX_THREADS 1024
00071 #define MAX_IN_QUEUE 128
00072 
00073 #include <unistd.h>
00074 #include <stdlib.h>
00075 #include <string.h>
00076 
00077 #include "gwlib/gwlib.h"
00078 #include "gw/wap_push_pap_compiler.h"
00079 
00080 static long max_pushes = 1;
00081 static int verbose = 1,
00082            use_hardcoded = 0,
00083            num_urls = 0,
00084            use_headers = 0,
00085            use_config = 0,
00086            accept_binary = 0, 
00087            use_numeric = 0,
00088            use_string = 0,
00089            use_content_header = 0,
00090            add_epilogue = 0,
00091            add_preamble = 0,
00092            use_dlr_mask = 0,
00093            use_dlr_url = 0;
00094 static double wait_seconds = 0.0;
00095 static Counter *counter = NULL;
00096 static char **push_data = NULL;
00097 static char *boundary = NULL;
00098 static Octstr *content_flag = NULL;
00099 static Octstr *appid_flag = NULL;
00100 static Octstr *appid_string = NULL;
00101 static Octstr *content_header = NULL;
00102 static Octstr *content_transfer_encoding = NULL;
00103 static Octstr *connection = NULL;
00104 static Octstr *delimiter = NULL;
00105 static Octstr *initiator_uri = NULL;
00106 static Octstr *dlr_mask = NULL;
00107 static Octstr *dlr_url = NULL;
00108 
00109 enum { SSL_CONNECTION_OFF = 0,
00110        DEFAULT_NUMBER_OF_RELOGS = 2};
00111 
00112 /*
00113  * Configuration variables
00114  */
00115 static int pi_ssl = SSL_CONNECTION_OFF;
00116 static long retries = DEFAULT_NUMBER_OF_RELOGS;
00117 static Octstr *ssl_client_certkey_file = NULL;
00118 static Octstr *push_url = NULL;
00119 static Octstr *pap_file = NULL;
00120 static Octstr *content_file = NULL;
00121 static Octstr *username = NULL;
00122 static Octstr *password = NULL;
00123 
00124 static void read_test_ppg_config(Octstr *name)
00125 {
00126     Cfg *cfg;
00127     CfgGroup *grp;
00128 
00129     cfg = cfg_create(name);
00130     if (cfg_read(cfg) == -1)
00131         panic(0, "Cannot read a configuration file %s, exiting",
00132               octstr_get_cstr(name));
00133     cfg_dump(cfg);
00134     grp = cfg_get_single_group(cfg, octstr_imm("test-ppg"));
00135     cfg_get_integer(&retries, grp, octstr_imm("retries"));
00136     cfg_get_bool(&pi_ssl, grp, octstr_imm("pi-ssl"));
00137 #ifdef HAVE_LIBSSL    
00138     if (pi_ssl) {
00139         ssl_client_certkey_file = cfg_get(grp, 
00140             octstr_imm("ssl-client-certkey-file"));
00141         if (ssl_client_certkey_file != NULL) {
00142             use_global_client_certkey_file(ssl_client_certkey_file);
00143         } else { 
00144             error(0, "cannot set up SSL without client certkey file");
00145             exit(1);
00146         }
00147     }
00148 #endif
00149 
00150     grp = cfg_get_single_group(cfg, octstr_imm("configuration"));
00151     push_url = cfg_get(grp, octstr_imm("push-url"));
00152     pap_file =  cfg_get(grp, octstr_imm("pap-file"));
00153     content_file =  cfg_get(grp, octstr_imm("content-file"));
00154     if (!use_hardcoded) {
00155         username = cfg_get(grp, octstr_imm("username"));
00156         password = cfg_get(grp, octstr_imm("password"));
00157     }
00158 
00159     cfg_destroy(cfg);
00160 }
00161 
00162 static void add_delimiter(Octstr **content)
00163 {
00164     if (octstr_compare(delimiter, octstr_imm("crlf")) == 0) {
00165         octstr_format_append(*content, "%c", '\r');
00166     }
00167 
00168     octstr_format_append(*content, "%c", '\n');
00169 }
00170 
00171 static void add_push_application_id(List **push_headers, Octstr *appid_flag,
00172                                     int use_string)
00173 {
00174     if (use_string) {
00175         gwlist_append(*push_headers, appid_string);
00176         return;
00177     }
00178 
00179     if (octstr_compare(appid_flag, octstr_imm("any")) == 0) {
00180         if (!use_numeric)
00181             http_header_add(*push_headers, "X-WAP-Application-Id", 
00182                             "http://www.wiral.com:*");
00183         else
00184             http_header_add(*push_headers, "X-WAP-Application-Id", "0");
00185     } else if (octstr_compare(appid_flag, octstr_imm("ua")) == 0) {
00186         if (!use_numeric)
00187             http_header_add(*push_headers, "X-WAP-Application-Id", 
00188                             "http://www.wiral.com:wml.ua");
00189         else
00190             http_header_add(*push_headers, "X-WAP-Application-Id", "2");
00191     } else if (octstr_compare(appid_flag, octstr_imm("mms")) == 0) {
00192         if (!use_numeric)
00193             http_header_add(*push_headers, "X-WAP-Application-Id", 
00194                             "mms.ua");
00195         else
00196             http_header_add(*push_headers, "X-WAP-Application-Id", "4");
00197     } else if (octstr_compare(appid_flag, octstr_imm("scrap")) == 0) {
00198         if (!use_numeric)
00199             http_header_add(*push_headers, "X-WAP-Application-Id", 
00200                         "no appid at all");
00201         else
00202             http_header_add(*push_headers, "X-WAP-Application-Id", 
00203                             "this is not a numeric header");
00204     }
00205 }
00206 
00207 static void add_dlr_mask(List **push_headers, Octstr *value)
00208 {
00209     http_header_add(*push_headers, "X-Kannel-DLR-Mask", 
00210                     octstr_get_cstr(value));
00211 }
00212 
00213 static void add_dlr_url(List **push_headers, Octstr *value)
00214 {
00215     http_header_add(*push_headers, "X-Kannel-DLR-Url",
00216                     octstr_get_cstr(value));
00217 }
00218 
00219 static void add_part_header(Octstr *content_keader, Octstr **wap_content)
00220 {
00221     if (use_content_header) {
00222         octstr_append(*wap_content, content_header);
00223     }
00224 
00225     add_delimiter(wap_content);
00226 }
00227 
00228 
00229 static void add_content_type(Octstr *content_flag, Octstr **wap_content)
00230 {
00231     if (octstr_compare(content_flag, octstr_imm("wml")) == 0)
00232         *wap_content = octstr_format("%s", 
00233             "Content-Type: text/vnd.wap.wml");
00234     else if (octstr_compare(content_flag, octstr_imm("si")) == 0)
00235         *wap_content = octstr_format("%s",
00236             "Content-Type: text/vnd.wap.si");
00237     else if (octstr_compare(content_flag, octstr_imm("sl")) == 0)
00238         *wap_content = octstr_format("%s",
00239             "Content-Type: text/vnd.wap.sl");
00240     else if (octstr_compare(content_flag, octstr_imm("multipart")) == 0)
00241         *wap_content = octstr_format("%s",
00242             "Content-Type: multipart/related; boundary=fsahgwruijkfldsa");
00243     else if (octstr_compare(content_flag, octstr_imm("mms")) == 0) 
00244         *wap_content = octstr_format("%s", 
00245             "Content-Type: application/vnd.wap.mms-message"); 
00246     else if (octstr_compare(content_flag, octstr_imm("scrap")) == 0)
00247         *wap_content = octstr_format("%s", "no type at all"); 
00248     else if (octstr_compare(content_flag, octstr_imm("nil")) == 0)
00249         *wap_content = octstr_create("");
00250     if (octstr_len(*wap_content) > 0)
00251         add_delimiter(wap_content);
00252 }
00253 
00254 static void add_content_transfer_encoding_type(Octstr *content_flag, 
00255                                                Octstr *wap_content)
00256 {
00257     if (!content_flag)
00258     return;
00259 
00260     if (octstr_compare(content_flag, octstr_imm("base64")) == 0)
00261     octstr_append_cstr(wap_content, "Content-transfer-encoding: base64");
00262 
00263     add_delimiter(&wap_content);
00264 }
00265 
00266 static void add_connection_header(List **push_headers, Octstr *connection)
00267 {
00268     if (!connection)
00269         return;
00270 
00271     if (octstr_compare(connection, octstr_imm("close")) == 0)
00272         http_header_add(*push_headers, "Connection", "close");
00273     else if (octstr_compare(connection, octstr_imm("keep-alive")) == 0) 
00274         http_header_add(*push_headers, "Connection", "keep-alive");
00275 }
00276 
00277 static void transfer_encode (Octstr *cte, Octstr *content)
00278 {
00279     if (!cte)
00280     return;
00281     
00282     if (octstr_compare(cte, octstr_imm("base64")) == 0) {
00283        octstr_binary_to_base64(content);
00284     }
00285 }
00286 
00287 
00288 /*
00289  * Add boundary value to the multipart header.
00290  */
00291 static Octstr *make_multipart_value(const char *boundary)
00292 {
00293     Octstr *hos;
00294     
00295     hos = octstr_format("%s", "multipart/related; boundary=");
00296     octstr_append(hos, octstr_imm(boundary));
00297     octstr_append(hos, octstr_imm("; type=\"application/xml\""));
00298     
00299     return hos;
00300 }
00301 
00302 static Octstr *make_part_delimiter(Octstr *boundary)
00303 {
00304     Octstr *part_delimiter;
00305 
00306     part_delimiter = octstr_create("");
00307     add_delimiter(&part_delimiter);
00308     octstr_format_append(part_delimiter, "%s", "--");
00309     octstr_append(part_delimiter, boundary);
00310     add_delimiter(&part_delimiter);
00311     
00312     return part_delimiter;
00313 }
00314 
00315 static Octstr *make_close_delimiter(Octstr *boundary)
00316 {
00317     Octstr *close_delimiter;
00318 
00319     close_delimiter = octstr_create("");
00320     add_delimiter(&close_delimiter);
00321     octstr_format_append(close_delimiter, "%s", "--");
00322     octstr_append(close_delimiter, boundary);
00323     octstr_format_append(close_delimiter, "%s", "--");
00324     /*add_delimiter(&close_delimiter);*/
00325 
00326     return close_delimiter;
00327 }
00328 
00329 static List *push_headers_create(size_t content_len)
00330 {
00331     List *push_headers;
00332     Octstr *mos;
00333 
00334     mos = NULL;
00335     push_headers = http_create_empty_headers();
00336     if (use_hardcoded)
00337         http_header_add(push_headers, "Content-Type", "multipart/related;" 
00338                         " boundary=asdlfkjiurwgasf; type=\"application/xml\"");
00339     else
00340         http_header_add(push_headers, "Content-Type", 
00341                         octstr_get_cstr(mos = make_multipart_value(boundary)));
00342     if (use_headers)
00343         http_add_basic_auth(push_headers, username, password);
00344     add_push_application_id(&push_headers, appid_flag, use_string);
00345     add_connection_header(&push_headers, connection);
00346     if (use_dlr_mask)
00347         add_dlr_mask(&push_headers, dlr_mask);
00348     if (use_dlr_url)
00349         add_dlr_url(&push_headers, dlr_url);
00350 
00351     octstr_destroy(mos);
00352 
00353     /* add initiator... */
00354     if (initiator_uri)
00355     http_header_add(push_headers, "X-Wap-Initiator-URI",
00356             octstr_get_cstr(initiator_uri));
00357 
00358     return push_headers;
00359 }
00360 
00361 static Octstr *push_content_create(void)
00362 {
00363     Octstr *push_content, 
00364            *wap_content;
00365     Octstr *wap_file_content,
00366            *pap_content,
00367            *pap_file_content,
00368            *bpos,
00369            *bcos;
00370 
00371     wap_content = NULL;
00372     push_content = NULL;
00373     if (use_hardcoded) {
00374         push_content = octstr_create("\r\n\r\n"
00375                   "--asdlfkjiurwgasf\r\n"
00376                   "Content-Type: application/xml\r\n\r\n"
00377                   "<?xml version=\"1.0\"?>"
00378                   "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP//EN\""
00379                              " \"http://www.wapforum.org/DTD/pap_1.0.dtd\">"
00380                   "<pap>"
00381                         "<push-message push-id=\"9fjeo39jf084@pi.com\""
00382                           " deliver-before-timestamp=\"2002-11-01T06:45:00Z\""
00383                           " deliver-after-timestamp=\"2000-02-27T06:45:00Z\""
00384                           " progress-notes-requested=\"false\">"
00385                  "<address address-value=\"WAPPUSH=+358408676001/"
00386                 "TYPE=PLMN@ppg.carrier.com\">"
00387                              "</address>"
00388                              "<quality-of-service"
00389                                " priority=\"low\""
00390                                " delivery-method=\"unconfirmed\""
00391                                " network-required=\"true\""
00392                                " network=\"GSM\""
00393                                " bearer-required=\"true\""
00394                                " bearer=\"SMS\">"
00395                              "</quality-of-service>"
00396                         "</push-message>"
00397                   "</pap>\r\n\r\n"         
00398                   "--asdlfkjiurwgasf\r\n"
00399                   "Content-Type: text/vnd.wap.si\r\n\r\n"
00400                   "<?xml version=\"1.0\"?>"
00401                   "<!DOCTYPE si PUBLIC \"-//WAPFORUM//DTD SI 1.0//EN\" "
00402                     " \"http://www.wapforum.org/DTD/si.dtd\">"
00403                   "<si>"
00404                       "<indication href=\"http://wap.iobox.fi\""
00405                           " si-id=\"1@wiral.com\""
00406                           " action=\"signal-high\""
00407                           " created=\"1999-06-25T15:23:15Z\""
00408                           " si-expires=\"2002-12-30T00:00:00Z\">"
00409                           "Want to test a fetch?"
00410                       "</indication>"
00411                    "</si>\r\n\r\n"
00412                  "--asdlfkjiurwgasf--\r\n\r\n"
00413                  "");
00414     } else {
00415         add_content_type(content_flag, &wap_content);
00416         add_content_transfer_encoding_type(content_transfer_encoding, 
00417                                            wap_content);
00418         add_part_header(content_header, &wap_content);
00419 
00420         /* Read the content file. (To be pushed)*/
00421         if ((wap_file_content = 
00422                 octstr_read_file(octstr_get_cstr(content_file))) == NULL)
00423              panic(0, "Stopping");
00424         if (accept_binary) {
00425             octstr_delete_matching(wap_file_content, octstr_imm(" "));
00426             octstr_delete_matching(wap_file_content, octstr_imm("\n"));
00427             octstr_delete_matching(wap_file_content, octstr_imm("\r"));
00428             if (!octstr_is_all_hex(wap_file_content))
00429                 panic(0, "non-hex chars in the content file, cannot continue");
00430             octstr_hex_to_binary(wap_file_content);            
00431         }
00432 
00433     transfer_encode(content_transfer_encoding, wap_file_content);
00434         octstr_append(wap_content, wap_file_content);
00435         octstr_destroy(wap_file_content);
00436 
00437         /* Read the control file. (To control pushing)*/
00438         pap_content = octstr_format("%s", "Content-Type: application/xml");
00439         add_delimiter(&pap_content);
00440         add_delimiter(&pap_content);
00441         if ((pap_file_content = 
00442                 octstr_read_file(octstr_get_cstr(pap_file))) ==  NULL)
00443             panic(0, "Stopping");
00444         
00445         octstr_append(pap_content, pap_file_content);
00446         octstr_destroy(pap_file_content);
00447 
00448         if (wap_content == NULL || pap_content == NULL)
00449             panic(0, "Cannot open the push content files");
00450 
00451         push_content = octstr_create("");
00452         if (add_preamble)
00453             octstr_append(push_content, octstr_imm("the parser should discard this"));
00454         octstr_append(push_content, 
00455             bpos = make_part_delimiter(octstr_imm(boundary)));
00456         /*octstr_append(push_content, octstr_imm("\r\n"));*/ /* Do we accept an additional 
00457                                                           * clrf ? */
00458         octstr_append(push_content, pap_content);
00459         octstr_append(push_content, bpos);
00460         octstr_destroy(bpos);
00461         octstr_append(push_content, wap_content);
00462         octstr_append(push_content, 
00463             bcos = make_close_delimiter(octstr_imm(boundary)));
00464         if (add_epilogue) {
00465             octstr_append(push_content, octstr_imm("\r\n"));
00466             octstr_append(push_content, octstr_imm("the parser should discard this"));
00467         }
00468         octstr_destroy(bcos);
00469         octstr_destroy(pap_content);
00470         octstr_destroy(wap_content);
00471     }
00472 
00473     return push_content;
00474 }
00475 
00476 static void make_url(Octstr **url)
00477 {
00478     if (use_config && !use_headers) {
00479         octstr_append(*url, octstr_imm("?username="));
00480         octstr_append(*url, username ? username : octstr_imm("default"));
00481         octstr_append(*url, octstr_imm("&password="));
00482         octstr_append(*url, password ? password: octstr_imm("default"));
00483     }
00484 }
00485 
00486 static void start_push(HTTPCaller *caller, long i)   
00487 {
00488     List *push_headers;
00489     Octstr *push_content;
00490     long *id;
00491     
00492     push_content = push_content_create();
00493     push_headers = push_headers_create(octstr_len(push_content));
00494     if (verbose) {
00495        debug("test.ppg", 0, "we have push content");
00496        octstr_dump(push_content, 0);
00497        debug("test.ppg", 0, "and headers");
00498        http_header_dump(push_headers);
00499     }
00500 
00501     id = gw_malloc(sizeof(long));
00502     *id = i;
00503     make_url(&push_url);
00504     debug("test.ppg", 0, "TEST_PPG: starting to push job %ld", i);
00505     http_start_request(caller, HTTP_METHOD_POST, push_url, push_headers, 
00506                        push_content, 0, id, ssl_client_certkey_file);
00507     debug("test.ppg", 0, "push done");
00508     octstr_destroy(push_content);
00509     http_destroy_headers(push_headers);
00510 }
00511 
00512 /*
00513  * Try log in defined number of times, when got response 401 and authentica-
00514  * tion info is in headers.
00515  */
00516 static int receive_push_reply(HTTPCaller *caller)
00517 {
00518     void *id;
00519     long *trid;
00520     int http_status,
00521         tries;
00522     List *reply_headers;
00523     Octstr *final_url,
00524            *auth_url,
00525            *reply_body,
00526            *os,
00527            *push_content,
00528            *auth_reply_body;
00529     WAPEvent *e;
00530     List *retry_headers;
00531     
00532     http_status = HTTP_UNAUTHORIZED;
00533     tries = 0;
00534 
00535     id = http_receive_result(caller, &http_status, &final_url, &reply_headers,
00536                              &reply_body);
00537 
00538     if (id == NULL || http_status == -1 || final_url == NULL) {
00539         error(0, "push failed, no reason found");
00540         goto push_failed;
00541     }
00542 
00543     while (use_headers && http_status == HTTP_UNAUTHORIZED && tries < retries) {
00544         debug("test.ppg", 0, "try number %d", tries);
00545         debug("test.ppg", 0, "authentication failure, get a challenge");
00546         http_destroy_headers(reply_headers);
00547         push_content = push_content_create();
00548         retry_headers = push_headers_create(octstr_len(push_content));
00549         http_add_basic_auth(retry_headers, username, password);
00550         trid = gw_malloc(sizeof(long));
00551         *trid = tries;
00552         http_start_request(caller, HTTP_METHOD_POST, final_url, retry_headers, 
00553                            push_content, 0, trid, NULL);
00554         debug("test.ppg ", 0, "TEST_PPG: doing response to %s", 
00555               octstr_get_cstr(final_url));
00556 
00557         octstr_destroy(push_content);
00558         http_destroy_headers(retry_headers);
00559         
00560         trid = http_receive_result(caller, &http_status, &auth_url, 
00561                                    &reply_headers, &auth_reply_body);
00562 
00563         if (trid == NULL || http_status == -1 || auth_url == NULL) {
00564             error(0, "unable to send authorisation, no reason found");
00565             goto push_failed;
00566         }   
00567 
00568         debug("test.ppg", 0, "TEST_PPG: send authentication to %s, retry %ld", 
00569                octstr_get_cstr(auth_url), *(long *) trid);
00570         gw_free(trid);
00571         octstr_destroy(auth_reply_body);
00572         octstr_destroy(auth_url);
00573         ++tries;
00574     }
00575 
00576     if (http_status == HTTP_NOT_FOUND) {
00577         error(0, "push failed, service not found");
00578         goto push_failed;
00579     }
00580 
00581     if (http_status == HTTP_FORBIDDEN) {
00582         error(0, "push failed, service forbidden");
00583         goto push_failed;
00584     }
00585 
00586     if (http_status == HTTP_UNAUTHORIZED) {
00587         if (use_headers)
00588             error(0, "tried %ld times, stopping", retries);
00589         else
00590             error(0, "push failed, authorisation failure");
00591         goto push_failed;
00592     }
00593         
00594     debug("test.ppg", 0, "TEST_PPG: push %ld done: reply from,  %s", 
00595           *(long *) id, octstr_get_cstr(final_url));
00596     gw_free(id);
00597     octstr_destroy(final_url);
00598 
00599     if (verbose)
00600         debug("test.ppg", 0, "TEST_PPG: reply headers were");
00601 
00602     while ((os = gwlist_extract_first(reply_headers)) != NULL) {
00603         if (verbose)
00604             octstr_dump(os, 0); 
00605         octstr_destroy(os);
00606     }
00607 
00608     if (verbose) {
00609         debug("test.ppg", 0, "TEST_PPG: reply body was");
00610         octstr_dump(reply_body, 0);
00611     }
00612 
00613     e = NULL;
00614     if (pap_compile(reply_body, &e) < 0) {
00615         warning(0, "TEST_PPG: receive_push_reply: cannot compile pap message");
00616         goto parse_error;
00617     }
00618 
00619     switch (e->type) {
00620         case Push_Response:
00621             debug("test.ppg", 0, "TEST_PPG: and type push response");
00622         break;
00623 
00624         case Bad_Message_Response:
00625             debug("test.ppg", 0, "TEST_PPG: and type bad message response");
00626         break;
00627 
00628         default:
00629             warning(0, "TEST_PPG: unknown event received from %s", 
00630                     octstr_get_cstr(final_url));
00631         break;
00632     }
00633 
00634     octstr_destroy(reply_body);
00635     wap_event_destroy(e);
00636     http_destroy_headers(reply_headers);
00637     return 0;
00638 
00639 push_failed:
00640     gw_free(id);
00641     octstr_destroy(final_url);
00642     octstr_destroy(reply_body);
00643     http_destroy_headers(reply_headers);
00644     return -1;
00645 
00646 parse_error:
00647     octstr_destroy(reply_body);
00648     http_destroy_headers(reply_headers);
00649     wap_event_destroy(e);
00650     return -1;
00651 }
00652 
00653 static void push_thread(void *arg)
00654 {
00655     HTTPCaller *caller;
00656     long succeeded, failed, in_queue;
00657     unsigned long i;
00658 
00659     caller = arg;
00660     succeeded = 0;
00661     failed = 0;   
00662     in_queue = 0;
00663     i = 0;
00664 
00665     for (;;) {
00666         while (in_queue < MAX_IN_QUEUE) {
00667             i = counter_increase(counter);
00668             if (i >= max_pushes)
00669                 goto receive_rest;
00670             start_push(caller, i);
00671             if (wait_seconds > 0)
00672                 gwthread_sleep(wait_seconds);
00673             ++in_queue;
00674         }
00675 
00676         while (in_queue >= MAX_IN_QUEUE) {
00677             if (receive_push_reply(caller) == -1)
00678                 ++failed;
00679             else
00680                 ++succeeded;
00681             --in_queue;
00682         }
00683     }
00684 
00685 receive_rest:
00686     while (in_queue > 0) {
00687         if (receive_push_reply(caller) == -1)
00688             ++failed;
00689         else
00690             ++succeeded;
00691         --in_queue;
00692     }
00693 
00694     http_caller_destroy(caller);
00695     info(0, "TEST_PPG: In thread %ld %ld succeeded, %ld failed", 
00696          (long) gwthread_self(), succeeded, failed);
00697 }
00698 
00699 static void help(void) 
00700 {
00701     info(0, "Usage: test_ppg [options] push_url [content_file pap_file]");
00702     info(0, "      or");
00703     info(0, "Usage: test_ppg [options] [conf_file]");
00704     info(0, "Implements push initiator for wap push. Push services are ");
00705     info(0, "located in push_url, push content in the file content file.");
00706     info(0, "File pap_file contains pap control document that controls");
00707     info(0, "pushing");
00708     info(0, "If option -H is not used, command line has either three or one");
00709     info(0, "arguments:");
00710     info(0, "      a) the url of the push proxy gateway");
00711     info(0, "      b) a file containing the content to be pushed");
00712     info(0, "      c) a pap document controlling pushing");
00713     info(0, "     or");
00714     info(0, "      a) a test configuration file, containing all these");
00715     info(0, "Option -H cannot be used with a configuration file. If it is");
00716     info(0, "used, the push url is the only argument.");
00717     info(0, "Options are:");
00718     info(0, "-h");
00719     info(0, "print this info");
00720     info(0, "-c content qualifier");
00721     info(0, "Define content type of the push content. Wml, multipart, nil,"); 
00722     info(0, "scrap, sl, and si accepted. Si is default, nil (no content"); 
00723     info(0, " type at all) and scrap (random string) are used for debugging");
00724     info(0, "-a application id");
00725     info(0, "Define the client application that will handle the push. Any,"); 
00726     info(0, "ua, mms, nil and scrap accepted, default ua.");
00727     info(0, "-n");
00728     info(0, "if set, use numeric appid values instead of string ones. For");
00729     info(0, "instance, '4' instead of 'mms.ua'. Default is off.");
00730     info(0, "-s string");
00731     info(0, "supply a message header as a plain string. For instance"); 
00732     info(0, "-s x-wap-application-id:mms.ua equals -a ua. Default is");
00733     info(0, "x-wap-application-id:mms.ua.");
00734     info(0, "-I string");
00735     info(0, "supply an initiator header as a plain string. For instance"); 
00736     info(0, "-I x-wap-application-id:http://foo.bar equals -I http://foo.bar");
00737     info(0, "-S string");
00738     info(0, "supply an additional part header (for push content) as a string."); 
00739     info(0, "For instance, -S Content-Language: en. Default no additional part");
00740     info(0, "headers.");
00741     info(0, "-b");
00742     info(0, "If true, send username/password in headers. Default false");
00743     info(0, "-v number");
00744     info(0, "    Set log level for stderr logging. Default 0 (debug)");
00745     info(0, "-q");
00746     info(0, "    Do not print debugging information");
00747     info(0, "Default: print it");
00748     info(0, "-r number");
00749     info(0, "    Make `number' requests. Default one request");
00750     info(0, "-i seconds");
00751     info(0, "    Wait 'seconds' seconds between pushes. Default: do not wait");
00752     info(0, "-e transfer encoding");
00753     info(0, "    use transfer encoding to send push contents.");
00754     info(0, "    Currently supported is base64.");
00755     info(0, "-k connection header");
00756     info(0, "Use the connection header. Keep-alive and close accepted,");
00757     info(0, "default close");
00758     info(0, "-H");
00759     info(0, "Use hardcoded MIME message, containing a pap control document.");
00760     info(0, "In addition, use hardcoded username/password in headers (if ");
00761     info(0, "flag -b is set, too");
00762     info(0, "Default: read components from files");
00763     info(0, "-t");
00764     info(0, "number of threads, maximum 1024, default 1");
00765     info(0, "-B");
00766     info(0, "accept binary push content. Default: off.");
00767     info(0, "Binary content consist of hex numbers. In addition, crs, lfs and");
00768     info(0, "spaces are accepted, and ignored.");
00769     info(0, "-d value");
00770     info(0, "set delimiter to be used. Accepted values crlf and lf. Default crlf.");
00771     info(0, "-E");
00772     info(0, "If set, add a hardcoded epilogue (epilogue is to be discarded anyway).");
00773     info(0, "Default off.");
00774     info(0, "-p");
00775     info(0, "If set, add hardcoded preamble. Default is off.");
00776     info(0, "-m value");
00777     info(0, "If set, add push header X-Kannel-DLR-Mask: value");
00778     info(0, "Default off.");
00779     info(0, "-u value");
00780     info(0, "If set, add push header X-Kannel-DLR-Url: value");
00781     info(0, "Default off.");
00782 }
00783 
00784 int main(int argc, char **argv)
00785 {
00786     int opt,
00787         num_threads;
00788     time_t start,
00789            end;
00790     double run_time;
00791     long threads[MAX_THREADS];
00792     long i;
00793     Octstr *fos;
00794 
00795     gwlib_init();
00796     num_threads = 1;
00797 
00798     while ((opt = getopt(argc, argv, "HhBbnEpv:qr:t:c:a:i:e:k:d:s:S:I:m:u:")) != EOF) {
00799         switch(opt) {
00800         case 'v':
00801             log_set_output_level(atoi(optarg));
00802         break;
00803 
00804         case 'q': 
00805             verbose = 0;
00806         break;  
00807 
00808         case 'r':
00809             max_pushes = atoi(optarg);      
00810         break; 
00811             
00812         case 'i': 
00813                 wait_seconds = atof(optarg);
00814         break;
00815 
00816             case 't': 
00817             num_threads = atoi(optarg);
00818                 if (num_threads > MAX_THREADS)
00819             num_threads = MAX_THREADS;
00820         break;
00821 
00822         case 'H': 
00823             use_hardcoded = 1;
00824         break;
00825 
00826         case 'c':
00827             content_flag = octstr_create(optarg);
00828             if (octstr_compare(content_flag, octstr_imm("wml")) != 0 && 
00829                     octstr_compare(content_flag, octstr_imm("si")) != 0 &&
00830                     octstr_compare(content_flag, octstr_imm("sl")) != 0 &&
00831                     octstr_compare(content_flag, octstr_imm("nil")) != 0 &&
00832                     octstr_compare(content_flag, octstr_imm("mms")) != 0 &&
00833                     octstr_compare(content_flag, octstr_imm("scrap")) != 0 &&
00834                     octstr_compare(content_flag, octstr_imm("multipart")) != 0) {
00835                 octstr_destroy(content_flag);
00836                 error(0, "TEST_PPG: Content type not known");
00837                 help();
00838                          exit(1);
00839             }
00840         break;
00841 
00842         case 'a':
00843             appid_flag = octstr_create(optarg);
00844                 if (octstr_compare(appid_flag, octstr_imm("any")) != 0 && 
00845                         octstr_compare(appid_flag, octstr_imm("ua")) != 0 &&
00846                         octstr_compare(appid_flag, octstr_imm("mms")) != 0 &&
00847                         octstr_compare(appid_flag, octstr_imm("nil")) != 0 &&
00848                         octstr_compare(appid_flag, octstr_imm("scrap")) != 0) {
00849         octstr_destroy(appid_flag);
00850         error(0, "TEST_PPG: Push application id not known");
00851         help();
00852                 exit(1);
00853            }
00854         break;
00855 
00856             case 'n':
00857                 use_numeric = 1;
00858             break;
00859 
00860             case 's':
00861                 appid_string = octstr_create(optarg);
00862                 use_string = 1;
00863             break;
00864 
00865             case 'S':
00866                 content_header = octstr_create(optarg);
00867                 use_content_header = 1;
00868             break;
00869 
00870         case 'e':
00871         content_transfer_encoding = octstr_create(optarg);
00872                 if (octstr_compare(content_transfer_encoding, octstr_imm("base64")) != 0) {
00873                 octstr_destroy(content_transfer_encoding);
00874             error(0, "TEST_PPG: unknown content transfer" 
00875                       " encoding \"%s\"", octstr_get_cstr(content_transfer_encoding));
00876             help();
00877                     exit(1);
00878         }
00879         break;
00880 
00881         case 'k':
00882             connection = octstr_create(optarg);
00883                 if (octstr_compare(connection, octstr_imm("close")) != 0 && 
00884                         octstr_compare(connection, octstr_imm("keep-alive")) != 0) {
00885                 octstr_destroy(connection);
00886             error(0, "TEST_PPG: Connection-header unacceptable");
00887             help();
00888                     exit(1);
00889                 }
00890         break;
00891 
00892         case 'h':
00893             help();
00894             exit(1);
00895 
00896         case 'b':
00897             use_headers = 1;
00898         break;
00899 
00900             case 'B':
00901                 accept_binary = 1;
00902             break;
00903 
00904             case 'd':
00905                 delimiter = octstr_create(optarg);
00906                 if (octstr_compare(delimiter, octstr_imm("crlf")) != 0 &&
00907                         octstr_compare(delimiter, octstr_imm("lf")) != 0) {
00908                     octstr_destroy(delimiter);
00909                     error(0, "illegal d value");
00910                     help();
00911                     exit(1);
00912                 }
00913             break;
00914 
00915             case 'E':
00916                 add_epilogue = 1;
00917             break;
00918 
00919             case 'p':
00920                 add_preamble = 1;
00921             break;
00922 
00923             case 'I':
00924                 initiator_uri = octstr_create(optarg);
00925         break;
00926 
00927             case 'm':
00928                 use_dlr_mask = 1;
00929                 dlr_mask = octstr_create(optarg);
00930             break;
00931 
00932             case 'u':
00933                 use_dlr_url = 1;
00934                 dlr_url = octstr_create(optarg);
00935             break;
00936 
00937     case '?':
00938         default:
00939             error(0, "TEST_PPG: Invalid option %c", opt);
00940             help();
00941             error(0, "Stopping");
00942             exit(1);
00943         }
00944     }
00945 
00946     if (optind == argc) {
00947         help();
00948         exit(1);
00949     }
00950     
00951     push_data = argv + optind;
00952     num_urls = argc - optind;
00953 
00954     if (content_flag == NULL)
00955         content_flag = octstr_imm("si");
00956 
00957     if (appid_flag == NULL)
00958         appid_flag = octstr_imm("ua");
00959 
00960     if (appid_string == NULL)
00961         appid_string = octstr_imm("x-wap-application-id: wml.ua");
00962 
00963     if (content_header == NULL)
00964         use_content_header = 0;
00965 
00966     if (dlr_mask == NULL)
00967         use_dlr_mask = 0;
00968 
00969     if (dlr_url == NULL)
00970         use_dlr_url = 0;
00971 
00972     if (delimiter == NULL)
00973         delimiter = octstr_imm("crlf");
00974 
00975     if (use_hardcoded) {
00976         username = octstr_imm("troo");
00977         password = octstr_imm("far");
00978     }
00979 
00980     if (push_data[0] == NULL) {
00981         error(0, "No ppg address or config file, stopping");
00982         exit(1);
00983     }
00984            
00985     use_config = 0;
00986     if (!use_hardcoded) {
00987         if (push_data[1] == NULL) {
00988             info(0, "a configuration file input assumed");
00989             read_test_ppg_config(fos = octstr_format("%s", push_data[0]));
00990             octstr_destroy(fos);
00991             use_config = 1;
00992         }
00993     }
00994 
00995     if (!use_config)
00996         push_url = octstr_format("%s", push_data[0]);
00997 
00998     if (!use_hardcoded && !use_config && push_data[1] != NULL) {
00999         if (push_data[2] == NULL) {
01000             error(0, "no pap control document, stopping");
01001             exit(1);
01002         } else {
01003            info(0, "an input without a configuration file assumed");
01004            content_file = octstr_create(push_data[1]);
01005            pap_file = octstr_create(push_data[2]);
01006            debug("test.ppg", 0, "using %s as a content file", push_data[1]);
01007            debug("test.ppg", 0, "using %s as a control file", push_data[2]);
01008         }
01009     }
01010 
01011     boundary = "asdlfkjiurwghasf";
01012     counter = counter_create();
01013 
01014     time(&start);
01015     if (num_threads == 0)
01016         push_thread(http_caller_create());
01017     else {
01018         for (i = 0; i < num_threads; ++i)
01019             threads[i] = gwthread_create(push_thread, http_caller_create());
01020         for (i = 0; i < num_threads; ++i)
01021             gwthread_join(threads[i]);
01022     }
01023     time(&end);
01024     run_time = difftime(end, start);
01025     info(0, "TEST_PPG: %ld requests in %f seconds, %f requests per second",
01026          max_pushes, run_time, max_pushes / run_time);
01027 
01028     octstr_destroy(content_flag);
01029     octstr_destroy(appid_flag);
01030     octstr_destroy(content_header);
01031     octstr_destroy(content_file);
01032     octstr_destroy(pap_file);
01033     octstr_destroy(ssl_client_certkey_file);
01034     octstr_destroy(username);
01035     octstr_destroy(password);
01036     octstr_destroy(push_url);
01037     octstr_destroy(connection);
01038     octstr_destroy(delimiter);
01039     octstr_destroy(dlr_mask);
01040     octstr_destroy(dlr_url);
01041     counter_destroy(counter);
01042     gwlib_shutdown();
01043 
01044     exit(0);
01045 }
01046 
01047 
01048 
01049 
01050 
01051 
01052 
01053 
01054 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.