📄 drive_wapbox.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 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 <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* drive_wapbox.c - test wapbox through its bearerbox and http interfaces * * This program starts a wapbox and pretends to be both the bearer box * and the http server, so that it can test and benchmark the wapbox in * isolation. * * Richard Braakman */#include <string.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include "gwlib/gwlib.h"#include "gw/msg.h"/* These should really be in a header file */enum wsp_types { Bad_PDU = -1, Connect_PDU = 0x01, ConnectReply_PDU = 0x02, Redirect_PDU = 0x03, Reply_PDU = 0x04, Disconnect_PDU = 0x05, Push_PDU = 0x06, ConfirmedPush_PDU = 0x07, Suspend_PDU = 0x08, Resume_PDU = 0x09, Get_PDU = 0x40, Options_PDU = 0x41, Head_PDU = 0x42, Delete_PDU = 0x43, Trace_PDU = 0x44, Post_PDU = 0x60, Put_PDU = 0x61};enum wtp_types { INVOKE = 1, RESULT = 2, ACK = 3};#define WSP_VERSION 0x10#define TIMEOUT 10.0 /* seconds */static long max_requests = 1;static long max_clients = 1;static long req_per_session = 1;static unsigned short http_port;static int wapbox_port = 30188;static Octstr *http_url = NULL;static int verbose_debug = 0;static int user_ack = 0;static long requests_complete = 0;static volatile sig_atomic_t dying = 0;enum WTP_type { TR_Invoke = 1, TR_Result = 2, TR_Ack = 3, TR_Abort = 4};struct client_status { /* True if we expect a WTP reply */ int wtp_invoked; /* Transaction number for WTP level */ int wtp_tid; /* current tid if wtp_invoked, else next tid to use */ /* True if we're connected at the WSP level */ /* Equal to 2 if we're trying to disconnect */ int wsp_connected; /* -1 if we're not connected */ long wsp_session_id; /* Number of successful page fetches this session */ int pages_fetched; /* Source port to use for this client; should be unique. */ unsigned short port;};typedef struct client_status Client; static Client *clients;List *ready_clients;static unsigned long get_varint(Octstr *pdu, int pos) { int c; long result = 0; do { c = octstr_get_char(pdu, pos++); result = (result << 7) | (c & 0x7f); } while (c & 0x80); return c;}static void http_thread(void *arg) { HTTPClient *client; Octstr *ip; Octstr *url; List *headers; Octstr *body; List *cgivars; Octstr *reply_body = octstr_create( "<?xml version=\"1.0\"?>\n" "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"\n" " \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n" "<wml>\n" "<card id=\"main\" title=\"Hello, world\" newcontext=\"true\">\n" " <p>Hello, world.</p>\n" "</card></wml>\n"); List *reply_headers = list_create(); int port; port = *(int *) arg; gw_free(arg); list_append(reply_headers, octstr_create("Content-Type: text/vnd.wap.wml")); for (;!dying;) { client = http_accept_request(port, &ip, &url, &headers, &body, &cgivars); if (client == NULL) break; http_send_reply(client, HTTP_OK, reply_headers, reply_body); http_destroy_headers(headers); octstr_destroy(ip); octstr_destroy(url); octstr_destroy(body); http_destroy_cgiargs(cgivars); } octstr_destroy(reply_body); http_destroy_headers(reply_headers);} static long http_thread_id;static int start_http_thread(void) { unsigned short port; int *port_copy; int ssl = 0; /* indicate if SSL-enabled server should be used */ for (port = 40000; port < 41000; port += 13) { if (http_open_port(port, ssl) != -1) break; } if (port == 41000) panic(0, "No ports available for http server"); port_copy = gw_malloc(sizeof(*port_copy)); *port_copy = port; http_thread_id = gwthread_create(http_thread, port_copy); if (http_thread_id == -1) panic(0, "Cannot start http thread"); return port;}static Connection *start_wapbox(void) { int wap_socket; int wapbox; wap_socket = make_server_socket(wapbox_port, NULL); if (wap_socket < 0) panic(0, "Couldn't make wapbox port\n"); wapbox = accept(wap_socket, NULL, NULL); if (wapbox < 0) panic(errno, "Wapbox could not connect\n"); close(wap_socket); return conn_wrap_fd(wapbox, 0);}static void initialize_clients(void) { long i; ready_clients = list_create(); clients = gw_malloc(max_clients * sizeof(*clients)); for (i = 0; i < max_clients; i++) { clients[i].wtp_invoked = 0; clients[i].wtp_tid = 0; clients[i].wsp_connected = 0; clients[i].wsp_session_id = -1; clients[i].pages_fetched = 0; clients[i].port = i; list_append(ready_clients, &clients[i]); }}static void destroy_clients(void) { gw_free(clients); list_destroy(ready_clients, NULL);}static Client *find_client(unsigned short port) { /* It's easy and fast since we assign ports in linear order */ if (port >= max_clients) return NULL; return clients + port;}static void client_done(Client *client) { requests_complete++; list_append(ready_clients, client);}static void increment_tid(Client *client) { if (client->wtp_tid == 0x7fff) client->wtp_tid = 0; else client->wtp_tid++;}/* Set the U/P flag on an Invoke PDU */static void set_user_ack(Octstr *pdu) { octstr_set_bits(pdu, 3 * 8 + 3, 1, 1);}static Octstr *wtp_invoke_create(int class) { Octstr *pdu; /* data describes a TR-Invoke PDU, with GTR=1 and TTR=1 (segmentation * not supported), and Transaction class 0 (which we replace below) */ static unsigned char data[] = { 0x0e, 0x00, 0x00, 0x00 }; gw_assert(class >= 0); gw_assert(class <= 2); pdu = octstr_create_from_data(data, sizeof(data)); octstr_set_char(pdu, 3, class); if (user_ack) set_user_ack(pdu); return pdu;}static Octstr *wtp_ack_create(void) { static unsigned char data[] = { 0x18, 0x00, 0x00 }; return octstr_create_from_data(data, sizeof(data));}static void add_wsp_connect(Octstr *pdu) { static unsigned char data[] = { Connect_PDU, WSP_VERSION, 68, 0x00, 0x03, 0x80, 0x90, 0x00, 0x03, 0x81, 0x90, 0x00, 0x02, 0x82, 0x30, 0x02, 0x83, 0x01, 0x02, 0x84, 0x01, 0x28, 0x85, 0x50, 0x58, 0x2d, 0x55, 0x50, 0x2d, 0x41, 0x47, 0x45, 0x54, 0x00, 0x51, 0x58, 0x2d, 0x55, 0x50, 0x2d, 0x47, 0x45, 0x54, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x00, 0x70, 0x58, 0x2d, 0x55, 0x50, 0x2d, 0x41, 0x50, 0x4f, 0x53, 0x54, 0x00, 0x09, 0x86, 0x02, 0x78, 0x2d, 0x75, 0x70, 0x2d, 0x31, 0x00 }; octstr_append_data(pdu, data, sizeof(data));}static void add_wsp_get(Octstr *pdu) { Octstr *urlbuf; octstr_append_char(pdu, Get_PDU); if (http_url) { octstr_append_uintvar(pdu, octstr_len(http_url)); octstr_append(pdu, http_url); } else { urlbuf = octstr_format("http://localhost:%ld/hello.wml", (long) http_port); octstr_append_uintvar(pdu, octstr_len(urlbuf)); octstr_append(pdu, urlbuf); octstr_destroy(urlbuf); }}static void add_wsp_disconnect(Octstr *pdu, long session_id) { octstr_append_char(pdu, Disconnect_PDU); octstr_append_uintvar(pdu, session_id);}static void set_tid(Octstr *pdu, int tid) { int c; /* Tid wraps at 15 bits. */ tid &= 0x7fff; c = octstr_get_char(pdu, 1); c = (tid >> 8) | (c & 0x80); octstr_set_char(pdu, 1, c); octstr_set_char(pdu, 2, tid & 0xff);}static int get_tid(Octstr *pdu) { return octstr_get_bits(pdu, 8, 16);}static int wtp_type(Octstr *pdu) { return octstr_get_bits(pdu, 1, 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -