/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2005 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see . * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * A very simple push initiator for testing a push proxy gateway * * Read pap control content and push content from files, pack them into a PAP * protocol MIME message and invoke push services specified by an url. Use a * hardcoded message boundary (asdlfkjiurwgasf), for simpler command line * interface. * Repetitions and use of multiple threads can be requested, in addition of * setting of some headers. * * By Aarno Syvänen for Wiral Ltd and Global Networks Inc. */ #define MAX_THREADS 1024 #define MAX_IN_QUEUE 128 #include #include #include #include "gwlib/gwlib.h" #include "gw/wap_push_pap_compiler.h" static long max_pushes = 1; static int verbose = 1, use_hardcoded = 0, num_urls = 0, use_headers = 0, use_config = 0, accept_binary = 0, use_numeric = 0, use_string = 0, use_content_header = 0, add_epilogue = 0, add_preamble = 0, use_dlr_mask = 0, use_dlr_url = 0; static double wait_seconds = 0.0; static Counter *counter = NULL; static char **push_data = NULL; static char *boundary = NULL; static Octstr *content_flag = NULL; static Octstr *appid_flag = NULL; static Octstr *appid_string = NULL; static Octstr *content_header = NULL; static Octstr *content_transfer_encoding = NULL; static Octstr *connection = NULL; static Octstr *delimiter = NULL; static Octstr *initiator_uri = NULL; static Octstr *dlr_mask = NULL; static Octstr *dlr_url = NULL; enum { SSL_CONNECTION_OFF = 0, DEFAULT_NUMBER_OF_RELOGS = 2}; /* * Configuration variables */ static int pi_ssl = SSL_CONNECTION_OFF; static long retries = DEFAULT_NUMBER_OF_RELOGS; static Octstr *ssl_client_certkey_file = NULL; static Octstr *push_url = NULL; static Octstr *pap_file = NULL; static Octstr *content_file = NULL; static Octstr *username = NULL; static Octstr *password = NULL; static void read_test_ppg_config(Octstr *name) { Cfg *cfg; CfgGroup *grp; cfg = cfg_create(name); if (cfg_read(cfg) == -1) panic(0, "Cannot read a configuration file %s, exiting", octstr_get_cstr(name)); cfg_dump(cfg); grp = cfg_get_single_group(cfg, octstr_imm("test-ppg")); cfg_get_integer(&retries, grp, octstr_imm("retries")); cfg_get_bool(&pi_ssl, grp, octstr_imm("pi-ssl")); #ifdef HAVE_LIBSSL if (pi_ssl) { ssl_client_certkey_file = cfg_get(grp, octstr_imm("ssl-client-certkey-file")); if (ssl_client_certkey_file != NULL) { use_global_client_certkey_file(ssl_client_certkey_file); } else { error(0, "cannot set up SSL without client certkey file"); exit(1); } } #endif grp = cfg_get_single_group(cfg, octstr_imm("configuration")); push_url = cfg_get(grp, octstr_imm("push-url")); pap_file = cfg_get(grp, octstr_imm("pap-file")); content_file = cfg_get(grp, octstr_imm("content-file")); if (!use_hardcoded) { username = cfg_get(grp, octstr_imm("username")); password = cfg_get(grp, octstr_imm("password")); } cfg_destroy(cfg); } static void add_delimiter(Octstr **content) { if (octstr_compare(delimiter, octstr_imm("crlf")) == 0) { octstr_format_append(*content, "%c", '\r'); } octstr_format_append(*content, "%c", '\n'); } static void add_push_application_id(List **push_headers, Octstr *appid_flag, int use_string) { if (use_string) { gwlist_append(*push_headers, appid_string); return; } if (octstr_compare(appid_flag, octstr_imm("any")) == 0) { if (!use_numeric) http_header_add(*push_headers, "X-WAP-Application-Id", "http://www.wiral.com:*"); else http_header_add(*push_headers, "X-WAP-Application-Id", "0"); } else if (octstr_compare(appid_flag, octstr_imm("ua")) == 0) { if (!use_numeric) http_header_add(*push_headers, "X-WAP-Application-Id", "http://www.wiral.com:wml.ua"); else http_header_add(*push_headers, "X-WAP-Application-Id", "2"); } else if (octstr_compare(appid_flag, octstr_imm("mms")) == 0) { if (!use_numeric) http_header_add(*push_headers, "X-WAP-Application-Id", "mms.ua"); else http_header_add(*push_headers, "X-WAP-Application-Id", "4"); } else if (octstr_compare(appid_flag, octstr_imm("scrap")) == 0) { if (!use_numeric) http_header_add(*push_headers, "X-WAP-Application-Id", "no appid at all"); else http_header_add(*push_headers, "X-WAP-Application-Id", "this is not a numeric header"); } } static void add_dlr_mask(List **push_headers, Octstr *value) { http_header_add(*push_headers, "X-Kannel-DLR-Mask", octstr_get_cstr(value)); } static void add_dlr_url(List **push_headers, Octstr *value) { http_header_add(*push_headers, "X-Kannel-DLR-Url", octstr_get_cstr(value)); } static void add_part_header(Octstr *content_keader, Octstr **wap_content) { if (use_content_header) { octstr_append(*wap_content, content_header); } add_delimiter(wap_content); } static void add_content_type(Octstr *content_flag, Octstr **wap_content) { if (octstr_compare(content_flag, octstr_imm("wml")) == 0) *wap_content = octstr_format("%s", "Content-Type: text/vnd.wap.wml"); else if (octstr_compare(content_flag, octstr_imm("si")) == 0) *wap_content = octstr_format("%s", "Content-Type: text/vnd.wap.si"); else if (octstr_compare(content_flag, octstr_imm("sl")) == 0) *wap_content = octstr_format("%s", "Content-Type: text/vnd.wap.sl"); else if (octstr_compare(content_flag, octstr_imm("multipart")) == 0) *wap_content = octstr_format("%s", "Content-Type: multipart/related; boundary=fsahgwruijkfldsa"); else if (octstr_compare(content_flag, octstr_imm("mms")) == 0) *wap_content = octstr_format("%s", "Content-Type: application/vnd.wap.mms-message"); else if (octstr_compare(content_flag, octstr_imm("scrap")) == 0) *wap_content = octstr_format("%s", "no type at all"); else if (octstr_compare(content_flag, octstr_imm("nil")) == 0) *wap_content = octstr_create(""); if (octstr_len(*wap_content) > 0) add_delimiter(wap_content); } static void add_content_transfer_encoding_type(Octstr *content_flag, Octstr *wap_content) { if (!content_flag) return; if (octstr_compare(content_flag, octstr_imm("base64")) == 0) octstr_append_cstr(wap_content, "Content-transfer-encoding: base64"); add_delimiter(&wap_content); } static void add_connection_header(List **push_headers, Octstr *connection) { if (!connection) return; if (octstr_compare(connection, octstr_imm("close")) == 0) http_header_add(*push_headers, "Connection", "close"); else if (octstr_compare(connection, octstr_imm("keep-alive")) == 0) http_header_add(*push_headers, "Connection", "keep-alive"); } static void transfer_encode (Octstr *cte, Octstr *content) { if (!cte) return; if (octstr_compare(cte, octstr_imm("base64")) == 0) { octstr_binary_to_base64(content); } } /* * Add boundary value to the multipart header. */ static Octstr *make_multipart_value(const char *boundary) { Octstr *hos; hos = octstr_format("%s", "multipart/related; boundary="); octstr_append(hos, octstr_imm(boundary)); octstr_append(hos, octstr_imm("; type=\"application/xml\"")); return hos; } static Octstr *make_part_delimiter(Octstr *boundary) { Octstr *part_delimiter; part_delimiter = octstr_create(""); add_delimiter(&part_delimiter); octstr_format_append(part_delimiter, "%s", "--"); octstr_append(part_delimiter, boundary); add_delimiter(&part_delimiter); return part_delimiter; } static Octstr *make_close_delimiter(Octstr *boundary) { Octstr *close_delimiter; close_delimiter = octstr_create(""); add_delimiter(&close_delimiter); octstr_format_append(close_delimiter, "%s", "--"); octstr_append(close_delimiter, boundary); octstr_format_append(close_delimiter, "%s", "--"); /*add_delimiter(&close_delimiter);*/ return close_delimiter; } static List *push_headers_create(size_t content_len) { List *push_headers; Octstr *mos; mos = NULL; push_headers = http_create_empty_headers(); if (use_hardcoded) http_header_add(push_headers, "Content-Type", "multipart/related;" " boundary=asdlfkjiurwgasf; type=\"application/xml\""); else http_header_add(push_headers, "Content-Type", octstr_get_cstr(mos = make_multipart_value(boundary))); if (use_headers) http_add_basic_auth(push_headers, username, password); add_push_application_id(&push_headers, appid_flag, use_string); add_connection_header(&push_headers, connection); if (use_dlr_mask) add_dlr_mask(&push_headers, dlr_mask); if (use_dlr_url) add_dlr_url(&push_headers, dlr_url); octstr_destroy(mos); /* add initiator... */ if (initiator_uri) http_header_add(push_headers, "X-Wap-Initiator-URI", octstr_get_cstr(initiator_uri)); return push_headers; } static Octstr *push_content_create(void) { Octstr *push_content, *wap_content; Octstr *wap_file_content, *pap_content, *pap_file_content, *bpos, *bcos; wap_content = NULL; push_content = NULL; if (use_hardcoded) { push_content = octstr_create("\r\n\r\n" "--asdlfkjiurwgasf\r\n" "Content-Type: application/xml\r\n\r\n" "" "" "" "" "
" "
" "" "" "
" "
\r\n\r\n" "--asdlfkjiurwgasf\r\n" "Content-Type: text/vnd.wap.si\r\n\r\n" "" "" "" "" "Want to test a fetch?" "" "\r\n\r\n" "--asdlfkjiurwgasf--\r\n\r\n" ""); } else { add_content_type(content_flag, &wap_content); add_content_transfer_encoding_type(content_transfer_encoding, wap_content); add_part_header(content_header, &wap_content); /* Read the content file. (To be pushed)*/ if ((wap_file_content = octstr_read_file(octstr_get_cstr(content_file))) == NULL) panic(0, "Stopping"); if (accept_binary) { octstr_delete_matching(wap_file_content, octstr_imm(" ")); octstr_delete_matching(wap_file_content, octstr_imm("\n")); octstr_delete_matching(wap_file_content, octstr_imm("\r")); if (!octstr_is_all_hex(wap_file_content)) panic(0, "non-hex chars in the content file, cannot continue"); octstr_hex_to_binary(wap_file_content); } transfer_encode(content_transfer_encoding, wap_file_content); octstr_append(wap_content, wap_file_content); octstr_destroy(wap_file_content); /* Read the control file. (To control pushing)*/ pap_content = octstr_format("%s", "Content-Type: application/xml"); add_delimiter(&pap_content); add_delimiter(&pap_content); if ((pap_file_content = octstr_read_file(octstr_get_cstr(pap_file))) == NULL) panic(0, "Stopping"); octstr_append(pap_content, pap_file_content); octstr_destroy(pap_file_content); if (wap_content == NULL || pap_content == NULL) panic(0, "Cannot open the push content files"); push_content = octstr_create(""); if (add_preamble) octstr_append(push_content, octstr_imm("the parser should discard this")); octstr_append(push_content, bpos = make_part_delimiter(octstr_imm(boundary))); /*octstr_append(push_content, octstr_imm("\r\n"));*/ /* Do we accept an additional * clrf ? */ octstr_append(push_content, pap_content); octstr_append(push_content, bpos); octstr_destroy(bpos); octstr_append(push_content, wap_content); octstr_append(push_content, bcos = make_close_delimiter(octstr_imm(boundary))); if (add_epilogue) { octstr_append(push_content, octstr_imm("\r\n")); octstr_append(push_content, octstr_imm("the parser should discard this")); } octstr_destroy(bcos); octstr_destroy(pap_content); octstr_destroy(wap_content); } return push_content; } static void make_url(Octstr **url) { if (use_config && !use_headers) { octstr_append(*url, octstr_imm("?username=")); octstr_append(*url, username ? username : octstr_imm("default")); octstr_append(*url, octstr_imm("&password=")); octstr_append(*url, password ? password: octstr_imm("default")); } } static void start_push(HTTPCaller *caller, long i) { List *push_headers; Octstr *push_content; long *id; push_content = push_content_create(); push_headers = push_headers_create(octstr_len(push_content)); if (verbose) { debug("test.ppg", 0, "we have push content"); octstr_dump(push_content, 0); debug("test.ppg", 0, "and headers"); http_header_dump(push_headers); } id = gw_malloc(sizeof(long)); *id = i; make_url(&push_url); debug("test.ppg", 0, "TEST_PPG: starting to push job %ld", i); http_start_request(caller, HTTP_METHOD_POST, push_url, push_headers, push_content, 0, id, ssl_client_certkey_file); debug("test.ppg", 0, "push done"); octstr_destroy(push_content); http_destroy_headers(push_headers); } /* * Try log in defined number of times, when got response 401 and authentica- * tion info is in headers. */ static int receive_push_reply(HTTPCaller *caller) { void *id; long *trid; int http_status, tries; List *reply_headers; Octstr *final_url, *auth_url, *reply_body, *os, *push_content, *auth_reply_body; WAPEvent *e; List *retry_headers; http_status = HTTP_UNAUTHORIZED; tries = 0; id = http_receive_result(caller, &http_status, &final_url, &reply_headers, &reply_body); if (id == NULL || http_status == -1 || final_url == NULL) { error(0, "push failed, no reason found"); goto push_failed; } while (use_headers && http_status == HTTP_UNAUTHORIZED && tries < retries) { debug("test.ppg", 0, "try number %d", tries); debug("test.ppg", 0, "authentication failure, get a challenge"); http_destroy_headers(reply_headers); push_content = push_content_create(); retry_headers = push_headers_create(octstr_len(push_content)); http_add_basic_auth(retry_headers, username, password); trid = gw_malloc(sizeof(long)); *trid = tries; http_start_request(caller, HTTP_METHOD_POST, final_url, retry_headers, push_content, 0, trid, NULL); debug("test.ppg ", 0, "TEST_PPG: doing response to %s", octstr_get_cstr(final_url)); octstr_destroy(push_content); http_destroy_headers(retry_headers); trid = http_receive_result(caller, &http_status, &auth_url, &reply_headers, &auth_reply_body); if (trid == NULL || http_status == -1 || auth_url == NULL) { error(0, "unable to send authorisation, no reason found"); goto push_failed; } debug("test.ppg", 0, "TEST_PPG: send authentication to %s, retry %ld", octstr_get_cstr(auth_url), *(long *) trid); gw_free(trid); octstr_destroy(auth_reply_body); octstr_destroy(auth_url); ++tries; } if (http_status == HTTP_NOT_FOUND) { error(0, "push failed, service not found"); goto push_failed; } if (http_status == HTTP_FORBIDDEN) { error(0, "push failed, service forbidden"); goto push_failed; } if (http_status == HTTP_UNAUTHORIZED) { if (use_headers) error(0, "tried %ld times, stopping", retries); else error(0, "push failed, authorisation failure"); goto push_failed; } debug("test.ppg", 0, "TEST_PPG: push %ld done: reply from, %s", *(long *) id, octstr_get_cstr(final_url)); gw_free(id); octstr_destroy(final_url); if (verbose) debug("test.ppg", 0, "TEST_PPG: reply headers were"); while ((os = gwlist_extract_first(reply_headers)) != NULL) { if (verbose) octstr_dump(os, 0); octstr_destroy(os); } if (verbose) { debug("test.ppg", 0, "TEST_PPG: reply body was"); octstr_dump(reply_body, 0); } e = NULL; if (pap_compile(reply_body, &e) < 0) { warning(0, "TEST_PPG: receive_push_reply: cannot compile pap message"); goto parse_error; } switch (e->type) { case Push_Response: debug("test.ppg", 0, "TEST_PPG: and type push response"); break; case Bad_Message_Response: debug("test.ppg", 0, "TEST_PPG: and type bad message response"); break; default: warning(0, "TEST_PPG: unknown event received from %s", octstr_get_cstr(final_url)); break; } octstr_destroy(reply_body); wap_event_destroy(e); http_destroy_headers(reply_headers); return 0; push_failed: gw_free(id); octstr_destroy(final_url); octstr_destroy(reply_body); http_destroy_headers(reply_headers); return -1; parse_error: octstr_destroy(reply_body); http_destroy_headers(reply_headers); wap_event_destroy(e); return -1; } static void push_thread(void *arg) { HTTPCaller *caller; long succeeded, failed, in_queue; unsigned long i; caller = arg; succeeded = 0; failed = 0; in_queue = 0; i = 0; for (;;) { while (in_queue < MAX_IN_QUEUE) { i = counter_increase(counter); if (i >= max_pushes) goto receive_rest; start_push(caller, i); if (wait_seconds > 0) gwthread_sleep(wait_seconds); ++in_queue; } while (in_queue >= MAX_IN_QUEUE) { if (receive_push_reply(caller) == -1) ++failed; else ++succeeded; --in_queue; } } receive_rest: while (in_queue > 0) { if (receive_push_reply(caller) == -1) ++failed; else ++succeeded; --in_queue; } http_caller_destroy(caller); info(0, "TEST_PPG: In thread %ld %ld succeeded, %ld failed", (long) gwthread_self(), succeeded, failed); } static void help(void) { info(0, "Usage: test_ppg [options] push_url [content_file pap_file]"); info(0, " or"); info(0, "Usage: test_ppg [options] [conf_file]"); info(0, "Implements push initiator for wap push. Push services are "); info(0, "located in push_url, push content in the file content file."); info(0, "File pap_file contains pap control document that controls"); info(0, "pushing"); info(0, "If option -H is not used, command line has either three or one"); info(0, "arguments:"); info(0, " a) the url of the push proxy gateway"); info(0, " b) a file containing the content to be pushed"); info(0, " c) a pap document controlling pushing"); info(0, " or"); info(0, " a) a test configuration file, containing all these"); info(0, "Option -H cannot be used with a configuration file. If it is"); info(0, "used, the push url is the only argument."); info(0, "Options are:"); info(0, "-h"); info(0, "print this info"); info(0, "-c content qualifier"); info(0, "Define content type of the push content. Wml, multipart, nil,"); info(0, "scrap, sl, and si accepted. Si is default, nil (no content"); info(0, " type at all) and scrap (random string) are used for debugging"); info(0, "-a application id"); info(0, "Define the client application that will handle the push. Any,"); info(0, "ua, mms, nil and scrap accepted, default ua."); info(0, "-n"); info(0, "if set, use numeric appid values instead of string ones. For"); info(0, "instance, '4' instead of 'mms.ua'. Default is off."); info(0, "-s string"); info(0, "supply a message header as a plain string. For instance"); info(0, "-s x-wap-application-id:mms.ua equals -a ua. Default is"); info(0, "x-wap-application-id:mms.ua."); info(0, "-I string"); info(0, "supply an initiator header as a plain string. For instance"); info(0, "-I x-wap-application-id:http://foo.bar equals -I http://foo.bar"); info(0, "-S string"); info(0, "supply an additional part header (for push content) as a string."); info(0, "For instance, -S Content-Language: en. Default no additional part"); info(0, "headers."); info(0, "-b"); info(0, "If true, send username/password in headers. Default false"); info(0, "-v number"); info(0, " Set log level for stderr logging. Default 0 (debug)"); info(0, "-q"); info(0, " Do not print debugging information"); info(0, "Default: print it"); info(0, "-r number"); info(0, " Make `number' requests. Default one request"); info(0, "-i seconds"); info(0, " Wait 'seconds' seconds between pushes. Default: do not wait"); info(0, "-e transfer encoding"); info(0, " use transfer encoding to send push contents."); info(0, " Currently supported is base64."); info(0, "-k connection header"); info(0, "Use the connection header. Keep-alive and close accepted,"); info(0, "default close"); info(0, "-H"); info(0, "Use hardcoded MIME message, containing a pap control document."); info(0, "In addition, use hardcoded username/password in headers (if "); info(0, "flag -b is set, too"); info(0, "Default: read components from files"); info(0, "-t"); info(0, "number of threads, maximum 1024, default 1"); info(0, "-B"); info(0, "accept binary push content. Default: off."); info(0, "Binary content consist of hex numbers. In addition, crs, lfs and"); info(0, "spaces are accepted, and ignored."); info(0, "-d value"); info(0, "set delimiter to be used. Accepted values crlf and lf. Default crlf."); info(0, "-E"); info(0, "If set, add a hardcoded epilogue (epilogue is to be discarded anyway)."); info(0, "Default off."); info(0, "-p"); info(0, "If set, add hardcoded preamble. Default is off."); info(0, "-m value"); info(0, "If set, add push header X-Kannel-DLR-Mask: value"); info(0, "Default off."); info(0, "-u value"); info(0, "If set, add push header X-Kannel-DLR-Url: value"); info(0, "Default off."); } int main(int argc, char **argv) { int opt, num_threads; time_t start, end; double run_time; long threads[MAX_THREADS]; long i; Octstr *fos; gwlib_init(); num_threads = 1; while ((opt = getopt(argc, argv, "HhBbnEpv:qr:t:c:a:i:e:k:d:s:S:I:m:u:")) != EOF) { switch(opt) { case 'v': log_set_output_level(atoi(optarg)); break; case 'q': verbose = 0; break; case 'r': max_pushes = atoi(optarg); break; case 'i': wait_seconds = atof(optarg); break; case 't': num_threads = atoi(optarg); if (num_threads > MAX_THREADS) num_threads = MAX_THREADS; break; case 'H': use_hardcoded = 1; break; case 'c': content_flag = octstr_create(optarg); if (octstr_compare(content_flag, octstr_imm("wml")) != 0 && octstr_compare(content_flag, octstr_imm("si")) != 0 && octstr_compare(content_flag, octstr_imm("sl")) != 0 && octstr_compare(content_flag, octstr_imm("nil")) != 0 && octstr_compare(content_flag, octstr_imm("mms")) != 0 && octstr_compare(content_flag, octstr_imm("scrap")) != 0 && octstr_compare(content_flag, octstr_imm("multipart")) != 0) { octstr_destroy(content_flag); error(0, "TEST_PPG: Content type not known"); help(); exit(1); } break; case 'a': appid_flag = octstr_create(optarg); if (octstr_compare(appid_flag, octstr_imm("any")) != 0 && octstr_compare(appid_flag, octstr_imm("ua")) != 0 && octstr_compare(appid_flag, octstr_imm("mms")) != 0 && octstr_compare(appid_flag, octstr_imm("nil")) != 0 && octstr_compare(appid_flag, octstr_imm("scrap")) != 0) { octstr_destroy(appid_flag); error(0, "TEST_PPG: Push application id not known"); help(); exit(1); } break; case 'n': use_numeric = 1; break; case 's': appid_string = octstr_create(optarg); use_string = 1; break; case 'S': content_header = octstr_create(optarg); use_content_header = 1; break; case 'e': content_transfer_encoding = octstr_create(optarg); if (octstr_compare(content_transfer_encoding, octstr_imm("base64")) != 0) { octstr_destroy(content_transfer_encoding); error(0, "TEST_PPG: unknown content transfer" " encoding \"%s\"", octstr_get_cstr(content_transfer_encoding)); help(); exit(1); } break; case 'k': connection = octstr_create(optarg); if (octstr_compare(connection, octstr_imm("close")) != 0 && octstr_compare(connection, octstr_imm("keep-alive")) != 0) { octstr_destroy(connection); error(0, "TEST_PPG: Connection-header unacceptable"); help(); exit(1); } break; case 'h': help(); exit(1); case 'b': use_headers = 1; break; case 'B': accept_binary = 1; break; case 'd': delimiter = octstr_create(optarg); if (octstr_compare(delimiter, octstr_imm("crlf")) != 0 && octstr_compare(delimiter, octstr_imm("lf")) != 0) { octstr_destroy(delimiter); error(0, "illegal d value"); help(); exit(1); } break; case 'E': add_epilogue = 1; break; case 'p': add_preamble = 1; break; case 'I': initiator_uri = octstr_create(optarg); break; case 'm': use_dlr_mask = 1; dlr_mask = octstr_create(optarg); break; case 'u': use_dlr_url = 1; dlr_url = octstr_create(optarg); break; case '?': default: error(0, "TEST_PPG: Invalid option %c", opt); help(); error(0, "Stopping"); exit(1); } } if (optind == argc) { help(); exit(1); } push_data = argv + optind; num_urls = argc - optind; if (content_flag == NULL) content_flag = octstr_imm("si"); if (appid_flag == NULL) appid_flag = octstr_imm("ua"); if (appid_string == NULL) appid_string = octstr_imm("x-wap-application-id: wml.ua"); if (content_header == NULL) use_content_header = 0; if (dlr_mask == NULL) use_dlr_mask = 0; if (dlr_url == NULL) use_dlr_url = 0; if (delimiter == NULL) delimiter = octstr_imm("crlf"); if (use_hardcoded) { username = octstr_imm("troo"); password = octstr_imm("far"); } if (push_data[0] == NULL) { error(0, "No ppg address or config file, stopping"); exit(1); } use_config = 0; if (!use_hardcoded) { if (push_data[1] == NULL) { info(0, "a configuration file input assumed"); read_test_ppg_config(fos = octstr_format("%s", push_data[0])); octstr_destroy(fos); use_config = 1; } } if (!use_config) push_url = octstr_format("%s", push_data[0]); if (!use_hardcoded && !use_config && push_data[1] != NULL) { if (push_data[2] == NULL) { error(0, "no pap control document, stopping"); exit(1); } else { info(0, "an input without a configuration file assumed"); content_file = octstr_create(push_data[1]); pap_file = octstr_create(push_data[2]); debug("test.ppg", 0, "using %s as a content file", push_data[1]); debug("test.ppg", 0, "using %s as a control file", push_data[2]); } } boundary = "asdlfkjiurwghasf"; counter = counter_create(); time(&start); if (num_threads == 0) push_thread(http_caller_create()); else { for (i = 0; i < num_threads; ++i) threads[i] = gwthread_create(push_thread, http_caller_create()); for (i = 0; i < num_threads; ++i) gwthread_join(threads[i]); } time(&end); run_time = difftime(end, start); info(0, "TEST_PPG: %ld requests in %f seconds, %f requests per second", max_pushes, run_time, max_pushes / run_time); octstr_destroy(content_flag); octstr_destroy(appid_flag); octstr_destroy(content_header); octstr_destroy(content_file); octstr_destroy(pap_file); octstr_destroy(ssl_client_certkey_file); octstr_destroy(username); octstr_destroy(password); octstr_destroy(push_url); octstr_destroy(connection); octstr_destroy(delimiter); octstr_destroy(dlr_mask); octstr_destroy(dlr_url); counter_destroy(counter); gwlib_shutdown(); exit(0); }