📄 wap-appl.c.backup
字号:
/* * gw/wap-appl.c - wapbox application layer and push ota indication, response * and confirmation primitive implementation. * * This module implements indication and confirmation primitives of WAP-189- * PushOTA-20000217-a (hereafter called ota). * In addition, WAP-200-WDP-20001212-a (wdp) is referred. * Wapbox application layer is not a Wapforum protocol. * * The application layer is reads events from its event queue, fetches the * corresponding URLs and feeds back events to the WSP layer (pull). * * In addition, the layer forwards WSP events related to push to the module * wap_push_ppg and wsp, implementing indications, responses and confirma- * tions of ota. * * Note that push header encoding and decoding are divided two parts: * first decoding and encoding numeric values and then packing these values * into WSP format and unpacking them from WSP format. This module contains * encoding part. * * Lars Wirzenius */#include <string.h>#include "gwlib/gwlib.h"#include "wmlscript/ws.h"#include "xml_shared.h"#include "wml_compiler.h"#include "wap/wap.h"#include "wap-appl.h"#include "wap/wsp_strings.h"#include "wap/wsp_caps.h"#include "wap/wsp.h"#ifdef ENABLE_COOKIES#include "wap/cookies.h"#endif#include "wap-error.h"/* * Give the status the module: * * limbo * not running at all * running * operating normally * terminating * waiting for operations to terminate, returning to limbo */static enum { limbo, running, terminating } run_status = limbo;/* * The queue of incoming events. */static List *queue = NULL;/* * HTTP caller identifier for application layer. */static HTTPCaller *caller = NULL;/* * Number of currently running HTTP fetching threads. */static Counter *fetches = NULL;/* * Charsets supported by WML compiler, queried from wml_compiler. */static List *charsets = NULL;struct content { Octstr *body; Octstr *type; Octstr *charset; Octstr *url;};/* * A mapping from HTTP request identifiers to information about the request. */struct request_data { long client_SDU_size; WAPEvent *event; long session_id; Octstr *url; long x_wap_tod; List *request_headers;};/* * WSP smart error messaging */extern int wsp_smart_errors;extern Octstr *device_home;/* * */static int have_ppg = 0;/* * Private functions. */static void main_thread(void *);static void start_fetch(WAPEvent *);static void return_replies_thread(void *);static void dev_null(const char *data, size_t len, void *context);static Octstr *convert_wml_to_wmlc(struct content *content);static Octstr *convert_wmlscript_to_wmlscriptc(struct content *content);static void wsp_http_map_url(Octstr **osp);static List *negotiate_capabilities(List *req_caps);static struct { char *type; char *result_type; Octstr *(*convert)(struct content *);} converters[] = { { "text/vnd.wap.wml", "application/vnd.wap.wmlc", convert_wml_to_wmlc }, { "text/vnd.wap.wmlscript", "application/vnd.wap.wmlscriptc", convert_wmlscript_to_wmlscriptc },};#define NUM_CONVERTERS ((long)(sizeof(converters) / sizeof(converters[0])))/* * Following functions implement indications and conformations part of Push * OTA protocol. */static void indicate_push_connection(WAPEvent *e);static void indicate_push_disconnect(WAPEvent *e);static void indicate_push_suspend(WAPEvent *e);static void indicate_push_resume(WAPEvent *e);static void confirm_push(WAPEvent *e);static void indicate_push_abort(WAPEvent *e);static void split_header_list(List **headers, List **new_headers, char *name);static void check_application_headers(List **headers, List **app_headers);static void decode_bearer_indication(List **headers, List **bearer_headers);static void response_push_connection(WAPEvent *e);/*********************************************************************** * The public interface to the application layer. */void wap_appl_init(Cfg *cfg) { gw_assert(run_status == limbo); queue = list_create(); fetches = counter_create(); list_add_producer(queue); run_status = running; charsets = wml_charsets(); caller = http_caller_create(); gwthread_create(main_thread, NULL); gwthread_create(return_replies_thread, NULL); if (cfg != NULL) have_ppg = 1; else have_ppg = 0;}void wap_appl_shutdown(void) { gw_assert(run_status == running); run_status = terminating; list_remove_producer(queue); gwthread_join_every(main_thread); http_caller_signal_shutdown(caller); gwthread_join_every(return_replies_thread); http_caller_destroy(caller); list_destroy(queue, wap_event_destroy_item); list_destroy(charsets, octstr_destroy_item); counter_destroy(fetches);}void wap_appl_dispatch(WAPEvent *event) { gw_assert(run_status == running); list_produce(queue, event);}long wap_appl_get_load(void) { gw_assert(run_status == running); return counter_value(fetches) + list_len(queue);}/*********************************************************************** * Private functions. *//* * When we have a push event, create ota indication or confirmation and send * it to ppg module. * Because Accept-Application and Bearer-Indication are optional, we cannot * rely on them. We must ask ppg main module do we have an open push session * for this initiator. Push is identified by push id. * If there is no ppg configured, do not refer to ppg's sessions' list. */static void main_thread(void *arg) { WAPEvent *ind, *res; long sid; WAPAddrTuple *tuple; while (run_status == running && (ind = list_consume(queue)) != NULL) { switch (ind->type) { case S_MethodInvoke_Ind: res = wap_event_create(S_MethodInvoke_Res); res->u.S_MethodInvoke_Res.server_transaction_id = ind->u.S_MethodInvoke_Ind.server_transaction_id; res->u.S_MethodInvoke_Res.session_id = ind->u.S_MethodInvoke_Ind.session_id; wsp_session_dispatch_event(res); start_fetch(ind); break; case S_Unit_MethodInvoke_Ind: start_fetch(ind); break; case S_Connect_Ind: tuple = ind->u.S_Connect_Ind.addr_tuple; if (have_ppg && wap_push_ppg_have_push_session_for(tuple)) { indicate_push_connection(ind); } else { res = wap_event_create(S_Connect_Res); /* FIXME: Not yet used by WSP layer */ res->u.S_Connect_Res.server_headers = NULL; res->u.S_Connect_Res.negotiated_capabilities = negotiate_capabilities( ind->u.S_Connect_Ind.requested_capabilities); res->u.S_Connect_Res.session_id = ind->u.S_Connect_Ind.session_id; wsp_session_dispatch_event(res); } wap_event_destroy(ind); break; case S_Disconnect_Ind: sid = ind->u.S_Disconnect_Ind.session_handle; if (have_ppg && wap_push_ppg_have_push_session_for_sid(sid)) indicate_push_disconnect(ind); wap_event_destroy(ind); break; case S_Suspend_Ind: sid = ind->u.S_Suspend_Ind.session_id; if (wap_push_ppg_have_push_session_for_sid(sid)) indicate_push_suspend(ind); wap_event_destroy(ind); break; case S_Resume_Ind: sid = ind->u.S_Resume_Ind.session_id; if (have_ppg && wap_push_ppg_have_push_session_for_sid(sid)) indicate_push_resume(ind); else { res = wap_event_create(S_Resume_Res); res->u.S_Resume_Res.server_headers = NULL; res->u.S_Resume_Res.session_id = ind->u.S_Resume_Ind.session_id; wsp_session_dispatch_event(res); } wap_event_destroy(ind); break; case S_MethodResult_Cnf: wap_event_destroy(ind); break; case S_ConfirmedPush_Cnf: confirm_push(ind); wap_event_destroy(ind); break; case S_MethodAbort_Ind: /* XXX Interrupt the fetch thread somehow */ wap_event_destroy(ind); break; case S_PushAbort_Ind: indicate_push_abort(ind); wap_event_destroy(ind); break; case Pom_Connect_Res: response_push_connection(ind); wap_event_destroy(ind); break; default: panic(0, "APPL: Can't handle %s event", wap_event_name(ind->type)); break; } }}static int convert_content(struct content *content) { Octstr *new_body; int failed = 0; int i; for (i = 0; i < NUM_CONVERTERS; i++) { if (octstr_str_compare(content->type, converters[i].type) == 0) { new_body = converters[i].convert(content); if (new_body != NULL) { octstr_destroy(content->body); content->body = new_body; octstr_destroy(content->type); content->type = octstr_create( converters[i].result_type); return 1; } failed = 1; } } if (failed) return -1; return 0;}/* Add a header identifying our gateway version */static void add_kannel_version(List *headers) { http_header_add(headers, "X-WAP-Gateway", GW_NAME "/" VERSION);}/* Add Accept-Charset: headers for stuff the WML compiler can * convert to UTF-8. *//* XXX This is not really correct, since we will not be able * to handle those charsets for all content types, just WML. */static void add_charset_headers(List *headers) { long i, len; gw_assert(charsets != NULL); len = list_len(charsets); for (i = 0; i < len; i++) { unsigned char *charset = octstr_get_cstr(list_get(charsets, i)); if (!http_charset_accepted(headers, charset)) http_header_add(headers, "Accept-Charset", charset); }}/* Add Accept: headers for stuff we can convert for the phone */static void add_accept_headers(List *headers) { int i; for (i = 0; i < NUM_CONVERTERS; i++) { if (http_type_accepted(headers, converters[i].result_type) && !http_type_accepted(headers, converters[i].type)) { http_header_add(headers, "Accept", converters[i].type); } }}static void add_network_info(List *headers, WAPAddrTuple *addr_tuple) { if (octstr_len(addr_tuple->remote->address) > 0) { http_header_add(headers, "X_Network_Info", octstr_get_cstr(addr_tuple->remote->address)); }}static void add_session_id(List *headers, long session_id) { if (session_id != -1) { char buf[40]; sprintf(buf, "%ld", session_id); http_header_add(headers, "X-WAP-Session-ID", buf); }}static void add_client_sdu_size(List *headers, long sdu_size) { if (sdu_size > 0) { Octstr *buf; buf = octstr_format("%ld", sdu_size); http_header_add(headers, "X-WAP-Client-SDU-Size", octstr_get_cstr(buf)); octstr_destroy(buf); }}static void add_via(List *headers) { Octstr *os; os = octstr_format("WAP/1.1 %S (" GW_NAME "/%s)", get_official_name(), VERSION); http_header_add(headers, "Via", octstr_get_cstr(os)); octstr_destroy(os);}/* * Add an X-WAP.TOD header to the response headers. It is defined in * the "WAP Caching Model" specification. * We generate it in textual form and let WSP header packing convert it * to binary form. */static void add_x_wap_tod(List *headers) { Octstr *gateway_time; gateway_time = date_format_http(time(NULL)); if (gateway_time == NULL) { warning(0, "Could not add X-WAP.TOD response header."); return; } http_header_add(headers, "X-WAP.TOD", octstr_get_cstr(gateway_time)); octstr_destroy(gateway_time);}static void add_referer_url(List *headers, Octstr *url) { if (octstr_len(url) > 0) { http_header_add(headers, "Referer", octstr_get_cstr(url)); }}static void set_referer_url(Octstr *url, WSPMachine *sm){ gw_assert(url != NULL); gw_assert(sm != NULL); octstr_destroy(sm->referer_url); sm->referer_url = octstr_duplicate(url);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -