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

wap-appl.c File Reference

#include <string.h>
#include "gwlib/gwlib.h"
#include "wmlscript/ws.h"
#include "xml_shared.h"
#include "wml_compiler.h"
#include "mime_decompiler.h"
#include "wap/wap.h"
#include "wap-appl.h"
#include "wap_push_ppg.h"
#include "wap/wsp_strings.h"
#include "wap/wsp_caps.h"
#include "wap/wsp.h"
#include "wap/cookies.h"
#include "radius/radius_acct.h"
#include "wap-error.h"
#include "wap-maps.h"

Include dependency graph for wap-appl.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  content
struct  request_data

Defines

#define ENABLE_NOT_ACCEPTED
#define NUM_CONVERTERS   ((long)(sizeof(converters) / sizeof(converters[0])))
#define NUM_DECONVERTERS   ((long)(sizeof(deconverters) / sizeof(deconverters[0])))
#define HEALTH_DECK

Enumerations

enum  { limbo, running, terminating }

Functions

void main_thread (void *)
void start_fetch (WAPEvent *)
void return_replies_thread (void *)
void dev_null (const char *data, size_t len, void *context)
Octstrconvert_wml_to_wmlc (struct content *content)
Octstrconvert_wmlscript_to_wmlscriptc (struct content *content)
Octstrdeconvert_multipart_formdata (struct content *content)
Listnegotiate_capabilities (List *req_caps)
void indicate_push_connection (WAPEvent *e)
void indicate_push_disconnect (WAPEvent *e)
void indicate_push_suspend (WAPEvent *e)
void indicate_push_resume (WAPEvent *e)
void confirm_push (WAPEvent *e)
void indicate_push_abort (WAPEvent *e)
void split_header_list (List **headers, List **new_headers, char *name)
void check_application_headers (List **headers, List **app_headers)
void decode_bearer_indication (List **headers, List **bearer_headers)
void response_push_connection (WAPEvent *e)
void wap_appl_init (Cfg *cfg)
void wap_appl_shutdown (void)
void wap_appl_dispatch (WAPEvent *event)
long wap_appl_get_load (void)
int convert_content (struct content *content, List *request_headers, int allow_empty)
int deconvert_content (struct content *content)
void add_kannel_version (List *headers)
void add_charset_headers (List *headers)
void add_accept_headers (List *headers)
void add_network_info (List *headers, WAPAddrTuple *addr_tuple)
void add_session_id (List *headers, long session_id)
void add_client_sdu_size (List *headers, long sdu_size)
void add_via (List *headers)
void add_x_wap_tod (List *headers)
void add_msisdn (List *headers, WAPAddrTuple *addr_tuple, Octstr *send_msisdn_header)
void set_referer_url (Octstr *url, WSPMachine *sm)
Octstrget_referer_url (const WSPMachine *sm)
void return_session_reply (long server_transaction_id, long status, List *headers, Octstr *body, long session_id)
void return_unit_reply (WAPAddrTuple *tuple, long transaction_id, long status, List *headers, Octstr *body)
void normalize_charset (struct content *content, List *device_headers)
void return_reply (int status, Octstr *content_body, List *headers, long sdu_size, WAPEvent *orig_event, long session_id, Octstr *method, Octstr *url, int x_wap_tod, List *request_headers, Octstr *msisdn)

Variables

enum { ... }  run_status
Listqueue = NULL
HTTPCallercaller = NULL
Counterfetches = NULL
Listcharsets = NULL
int wsp_smart_errors
Octstrdevice_home
int have_ppg = 0
struct {
   char *   type
   char *   result_type
   Octstr *(*   convert )(struct content *)
converters []
struct {
   char *   type
   char *   result_type
   Octstr *(*   deconvert )(struct content *)
deconverters []


Define Documentation

#define ENABLE_NOT_ACCEPTED
 

Definition at line 105 of file wap-appl.c.

#define HEALTH_DECK
 

Value:

"<?xml version=\"1.0\"?>" \
    "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD 1.1//EN\" " \
    "\"http://www.wapforum.org/DTD/wml_1.1.xml\">" \
    "<wml><card id=\"health\"><p>Ok</p></card></wml>"

Definition at line 1097 of file wap-appl.c.

Referenced by start_fetch().

#define NUM_CONVERTERS   ((long)(sizeof(converters) / sizeof(converters[0])))
 

Definition at line 212 of file wap-appl.c.

#define NUM_DECONVERTERS   ((long)(sizeof(deconverters) / sizeof(deconverters[0])))
 

Definition at line 228 of file wap-appl.c.


Enumeration Type Documentation

anonymous enum
 

Enumeration values:
limbo 
running 
terminating 

Definition at line 117 of file wap-appl.c.

00117 { limbo, running, terminating } run_status = limbo;


Function Documentation

void add_accept_headers List headers  )  [static]
 

Definition at line 523 of file wap-appl.c.

References converters, http_header_add(), http_type_accepted(), result_type, and type.

Referenced by start_fetch().

00524 {
00525     int i;
00526     
00527     for (i = 0; i < NUM_CONVERTERS; i++) {
00528         if (http_type_accepted(headers, "*/*") || (
00529             http_type_accepted(headers, converters[i].result_type)
00530             && !http_type_accepted(headers, converters[i].type))) {
00531             http_header_add(headers, "Accept", converters[i].type);
00532         }
00533     }
00534 }

Here is the call graph for this function:

void add_charset_headers List headers  )  [static]
 

Definition at line 515 of file wap-appl.c.

References http_charset_accepted(), and http_header_add().

Referenced by start_fetch().

00516 {
00517     if (!http_charset_accepted(headers, "utf-8"))
00518         http_header_add(headers, "Accept-Charset", "utf-8");
00519 }

Here is the call graph for this function:

void add_client_sdu_size List headers,
long  sdu_size
[static]
 

Definition at line 559 of file wap-appl.c.

References http_header_add(), octstr_destroy(), octstr_format(), and octstr_get_cstr.

Referenced by start_fetch().

00560 {
00561     if (sdu_size > 0) {
00562         Octstr *buf;
00563     
00564         buf = octstr_format("%ld", sdu_size);
00565         http_header_add(headers, "X-WAP-Client-SDU-Size", octstr_get_cstr(buf));
00566         octstr_destroy(buf);
00567     }
00568 }

Here is the call graph for this function:

void add_kannel_version List headers  )  [static]
 

Definition at line 505 of file wap-appl.c.

References GW_NAME, GW_VERSION, and http_header_add().

Referenced by start_fetch().

00506 {
00507     http_header_add(headers, "X-WAP-Gateway", GW_NAME "/" GW_VERSION);
00508 }

Here is the call graph for this function:

void add_msisdn List headers,
WAPAddrTuple addr_tuple,
Octstr send_msisdn_header
[static]
 

Definition at line 608 of file wap-appl.c.

References addr_tuple, WAPAddr::address, http_header_add(), http_header_remove_all(), http_header_value(), octstr_destroy(), octstr_get_cstr, octstr_len(), radius_acct_get_msisdn(), WAPAddrTuple::remote, and warning().

Referenced by start_fetch().

00610 {
00611     Octstr *msisdn = NULL;
00612     Octstr *value = NULL;
00613 
00614     if (send_msisdn_header == NULL || octstr_len(send_msisdn_header) == 0)
00615         return;
00616 
00617     /* 
00618      * Security considerations. If there are headers with the header name we
00619      * use to pass on the MSISDN number, then remove them.
00620      */
00621     if ((value = http_header_value(headers, send_msisdn_header)) != NULL) {
00622         warning(0, "MSISDN header <%s> already present on request, "
00623                    "header value=<%s>", octstr_get_cstr(send_msisdn_header), 
00624                   octstr_get_cstr(value));
00625         http_header_remove_all(headers, octstr_get_cstr(send_msisdn_header));
00626     }
00627 
00628     /* 
00629      * XXX Add generic msisdn provisioning cleanly in here!
00630      * See revision 1.89 for Bruno's try.
00631      */
00632 
00633     /* We do not accept NULL values to be added to the HTTP header */
00634     if ((msisdn = radius_acct_get_msisdn(addr_tuple->remote->address)) != NULL) {
00635         http_header_add(headers, octstr_get_cstr(send_msisdn_header), octstr_get_cstr(msisdn));
00636     }
00637 
00638     octstr_destroy(value);
00639     octstr_destroy(msisdn);
00640 }

Here is the call graph for this function:

void add_network_info List headers,
WAPAddrTuple addr_tuple
[static]
 

Definition at line 538 of file wap-appl.c.

References addr_tuple, WAPAddr::address, http_header_add(), octstr_get_cstr, octstr_len(), and WAPAddrTuple::remote.

Referenced by start_fetch().

00539 {
00540     if (octstr_len(addr_tuple->remote->address) > 0) {
00541         http_header_add(headers, "X-WAP-Network-Client-IP", 
00542                         octstr_get_cstr(addr_tuple->remote->address));
00543     }
00544 }

Here is the call graph for this function:

void add_session_id List headers,
long  session_id
[static]
 

Definition at line 548 of file wap-appl.c.

References http_header_add().

Referenced by start_fetch().

00549 {
00550     if (session_id != -1) {
00551         char buf[40];
00552         sprintf(buf, "%ld", session_id);
00553         http_header_add(headers, "X-WAP-Session-ID", buf);
00554     }
00555 }

Here is the call graph for this function:

void add_via List headers  )  [static]
 

Definition at line 571 of file wap-appl.c.

References get_official_name(), GW_NAME, GW_VERSION, http_header_add(), http_header_value(), octstr_destroy(), octstr_format(), octstr_get_cstr, and octstr_imm().

Referenced by start_fetch().

00572 {
00573     Octstr *os;
00574     Octstr *version;
00575     
00576     version = http_header_value(headers, octstr_imm("Encoding-Version"));
00577     os = octstr_format("WAP/%s %S (" GW_NAME "/%s)", 
00578                        (version ? octstr_get_cstr(version) : "1.1"),
00579                        get_official_name(), GW_VERSION);
00580     http_header_add(headers, "Via", octstr_get_cstr(os));
00581     octstr_destroy(os);
00582     octstr_destroy(version);
00583 }

Here is the call graph for this function:

void add_x_wap_tod List headers  )  [static]
 

Definition at line 592 of file wap-appl.c.

References date_format_http(), http_header_add(), octstr_destroy(), octstr_get_cstr, and warning().

Referenced by return_reply().

00593 {
00594     Octstr *gateway_time;
00595     
00596     gateway_time = date_format_http(time(NULL));
00597     if (gateway_time == NULL) {
00598         warning(0, "Could not add X-WAP.TOD response header.");
00599         return;
00600     }
00601     
00602     http_header_add(headers, "X-WAP.TOD", octstr_get_cstr(gateway_time));
00603     octstr_destroy(gateway_time);
00604 }

Here is the call graph for this function:

void check_application_headers List **  headers,
List **  app_headers
[static]
 

Definition at line 1462 of file wap-appl.c.

References debug(), error(), GW_ERROR, gwlist_len(), http_destroy_headers(), http_header_add(), http_header_dump(), http_header_get(), octstr_destroy(), octstr_dump, octstr_get_cstr, and split_header_list().

Referenced by indicate_push_connection().

01464 {
01465     List *inh;
01466     int i;
01467     Octstr *appid_name, *coded_octstr;
01468     char *appid_value, *coded_value;
01469 
01470     split_header_list(headers, &inh, "Accept-Application");
01471     
01472     if (*headers == NULL || gwlist_len(inh) == 0) {
01473         http_header_add(*application_headers, "Accept-Application", "wml ua");
01474         debug("wap.appl.push", 0, "APPL: No push application, assuming wml"
01475               " ua");
01476         if (*headers != NULL)
01477             http_destroy_headers(inh);
01478         return;
01479     }
01480 
01481     i = 0;
01482     coded_value = NULL;
01483     appid_value = NULL;
01484 
01485     while (gwlist_len(inh) > 0) {
01486         http_header_get(inh, i, &appid_name, &coded_octstr);
01487 
01488         /* Greatest value reserved by WINA is 0xFF00 0000*/
01489         coded_value = octstr_get_cstr(coded_octstr);
01490         if (coded_value != NULL)
01491        appid_value = (char *)wsp_application_id_to_cstr((long) coded_value);
01492 
01493         if (appid_value != NULL && coded_value != NULL)
01494             http_header_add(*application_headers, "Accept-Application", 
01495                             appid_value);
01496         else {
01497             error(0, "OTA: Unknown application is, skipping: ");
01498             octstr_dump(coded_octstr, 0, GW_ERROR);
01499         }
01500 
01501         i++;  
01502     }
01503    
01504     debug("wap.appl.push", 0, "application headers were");
01505     http_header_dump(*application_headers);
01506 
01507     http_destroy_headers(inh);
01508     octstr_destroy(appid_name);
01509     octstr_destroy(coded_octstr);
01510 }

Here is the call graph for this function:

void confirm_push WAPEvent e  )  [static]
 

Definition at line 1642 of file wap-appl.c.

References debug(), Po_ConfirmedPush_Cnf, WAPEvent::u, wap_event_create, and wap_push_ppg_dispatch_event().

01643 {
01644     WAPEvent *ppg_event;
01645 
01646     ppg_event = wap_event_create(Po_ConfirmedPush_Cnf);
01647     ppg_event->u.Po_ConfirmedPush_Cnf.server_push_id = 
01648         e->u.S_ConfirmedPush_Cnf.server_push_id;
01649     ppg_event->u.Po_ConfirmedPush_Cnf.session_handle = 
01650          e->u.S_ConfirmedPush_Cnf.session_id;
01651 
01652     debug("wap.appl", 0, "OTA: confirming push for ppg");
01653     wap_push_ppg_dispatch_event(ppg_event);
01654 }

Here is the call graph for this function:

int convert_content struct content content,
List request_headers,
int  allow_empty
[static]
 

Definition at line 421 of file wap-appl.c.

References content::body, converters, debug(), http_type_accepted(), octstr_create, octstr_destroy(), octstr_dump, octstr_get_cstr, octstr_len(), octstr_str_compare(), result_type, and content::type.

Referenced by return_reply().

00423 {
00424     Octstr *new_body;
00425     int failed = 0;
00426     int i;
00427 
00428     for (i = 0; i < NUM_CONVERTERS; i++) {
00429         if (octstr_str_compare(content->type, converters[i].type) == 0 &&
00430             !http_type_accepted(request_headers, octstr_get_cstr(content->type))) {
00431             debug("wap.convert",0,"WSP: Converting from <%s> to <%s>", 
00432                   octstr_get_cstr(content->type), converters[i].result_type);
00433             /* 
00434              * Note: if request is HEAD, body is empty and we still need to adapt
00435              * content-type but we don't need to convert a 0 bytes body 
00436              */
00437             if (allow_empty && octstr_len(content->body) == 0) 
00438                 return 1;
00439 
00440             new_body = converters[i].convert(content);
00441             if (new_body != NULL) {
00442                 long s = octstr_len(content->body);
00443                 octstr_destroy(content->body);
00444                 octstr_destroy(content->type);
00445                 content->body = new_body;
00446                 content->type = octstr_create(converters[i].result_type);
00447                 debug("wap.convert",0,"WSP: Content-type is "
00448                       "now <%s>, size %ld bytes (before: %ld bytes), content body is:", 
00449                       converters[i].result_type, octstr_len(new_body), s);
00450                 octstr_dump(new_body, 0);
00451                 return 1;
00452             }
00453             debug("wap.convert",0,"WSP: Content convertion failed!");
00454             failed = 1;
00455         }
00456     }
00457     
00458     return (failed ? -1 : 0);
00459 }

Here is the call graph for this function:

Octstr * convert_wml_to_wmlc struct content content  )  [static]
 

Definition at line 1316 of file wap-appl.c.

References content::body, content::charset, octstr_destroy(), content::version, warning(), and wml_compile().

01317 {
01318     Octstr *wmlc;
01319     int ret;
01320    
01321     /* content->charset is passed from the HTTP header parsing */
01322     ret = wml_compile(content->body, content->charset, &wmlc, 
01323                       content->version);
01324 
01325     /* wmlc is created implicitely in wml_compile() */
01326     if (ret == 0)
01327         return wmlc;
01328 
01329     octstr_destroy(wmlc);
01330     warning(0, "WSP: WML compilation failed.");
01331     return NULL;
01332 }

Here is the call graph for this function:

Octstr * convert_wmlscript_to_wmlscriptc struct content content  )  [static]
 

Definition at line 1335 of file wap-appl.c.

References content::body, octstr_create_from_data, octstr_get_cstr, octstr_len(), panic, result, content::url, warning(), ws_compile_data(), ws_create(), ws_result_to_string(), WsCompilerParams, WsCompilerPtr, and WsResult.

01336 {
01337     WsCompilerParams params;
01338     WsCompilerPtr compiler;
01339     WsResult result;
01340     unsigned char *result_data;
01341     size_t result_size;
01342     Octstr *wmlscriptc;
01343     
01344     memset(&params, 0, sizeof(params));
01345     params.use_latin1_strings = 0;
01346     params.print_symbolic_assembler = 0;
01347     params.print_assembler = 0;
01348     params.meta_name_cb = NULL;
01349     params.meta_name_cb_context = NULL;
01350     params.meta_http_equiv_cb = NULL;
01351     params.meta_http_equiv_cb_context = NULL;
01352     params.stdout_cb = dev_null;
01353     params.stderr_cb = dev_null;
01354     
01355     compiler = ws_create(&params);
01356     if (compiler == NULL) {
01357         panic(0, "WSP: could not create WMLScript compiler");
01358     }
01359     
01360     result = ws_compile_data(compiler, octstr_get_cstr(content->url),
01361                              (unsigned char *)octstr_get_cstr(content->body),
01362                              octstr_len(content->body),
01363                              &result_data, &result_size);
01364     if (result != WS_OK) {
01365         warning(0, "WSP: WMLScript compilation failed: %s",
01366                 ws_result_to_string(result));
01367         wmlscriptc = NULL;
01368     } else {
01369         wmlscriptc = octstr_create_from_data((char *)result_data, result_size);
01370     }
01371     
01372     return wmlscriptc;
01373 }

Here is the call graph for this function:

void decode_bearer_indication List **  headers,
List **  bearer_headers
[static]
 

Definition at line 1520 of file wap-appl.c.

References debug(), error(), GW_ERROR, gwlist_len(), http_destroy_headers(), http_header_add(), http_header_dump(), http_header_get(), name, octstr_dump, octstr_get_char(), and split_header_list().

Referenced by indicate_push_connection(), and indicate_push_resume().

01521 {
01522     List *inb;
01523     Octstr *name, *coded_octstr;
01524     char *value;
01525     unsigned char coded_value;
01526 
01527     if (*headers == NULL) {
01528         debug("wap.appl", 0, "APPL: no client headers, continuing");
01529         return;
01530     }
01531 
01532     split_header_list(headers, &inb, "Bearer-Indication");
01533 
01534     if (gwlist_len(inb) == 0) {
01535         debug("wap.appl.push", 0, "APPL: No bearer indication headers,"
01536               " continuing");
01537         http_destroy_headers(inb);
01538         return;  
01539     }
01540 
01541     if (gwlist_len(inb) > 1) {
01542         error(0, "APPL: To many bearer indication header(s), skipping"
01543               " them");
01544         http_destroy_headers(inb);
01545         return;
01546     }
01547 
01548     http_header_get(inb, 0, &name, &coded_octstr);
01549     http_destroy_headers(inb);
01550 
01551     /* Greatest assigned number for a bearer type is 0xff, see wdp, appendix C */
01552     coded_value = octstr_get_char(coded_octstr, 0);
01553     value = (char *)wsp_bearer_indication_to_cstr(coded_value);
01554 
01555     if (value != NULL && coded_value != 0) {
01556        http_header_add(*bearer_headers, "Bearer-Indication", value);
01557        debug("wap.appl.push", 0, "bearer indication header was");
01558        http_header_dump(*bearer_headers);
01559        return;
01560     } else {
01561        error(0, "APPL: Illegal bearer indication value, skipping:");
01562        octstr_dump(coded_octstr, 0, GW_ERROR);
01563        http_destroy_headers(*bearer_headers);
01564        return;
01565     }
01566 }

Here is the call graph for this function:

int deconvert_content struct content content  )  [static]
 

Definition at line 469 of file wap-appl.c.

References content::body, debug(), deconverters, octstr_create, octstr_destroy(), octstr_dump, octstr_get_cstr, octstr_len(), octstr_str_compare(), result_type, and content::type.

Referenced by start_fetch().

00470 {
00471     Octstr *new_body;
00472     int failed = 0;
00473     int i;
00474 
00475     debug("wap.deconvert",0,"WSP deconvert: Trying to deconvert:"); 
00476     octstr_dump(content->body, 0);
00477     for (i = 0; i < NUM_DECONVERTERS; i++) {
00478         if (octstr_str_compare(content->type, deconverters[i].type) == 0) {
00479             debug("wap.deconvert",0,"WSP: Deconverting from <%s> to <%s>", 
00480                   octstr_get_cstr(content->type), 
00481             deconverters[i].result_type);
00482             new_body = deconverters[i].deconvert(content);
00483             if (new_body != NULL) {
00484                 long s = octstr_len(content->body);
00485                 octstr_destroy(content->body);
00486                 octstr_destroy(content->type);
00487                 content->body = new_body;
00488                 content->type = octstr_create(deconverters[i].result_type);
00489                 debug("wap.convert",0,"WSP: Content-type is "
00490                       "now <%s>, size %ld bytes (before: %ld bytes), content body is:", 
00491                 deconverters[i].result_type, octstr_len(new_body), s);
00492                 octstr_dump(new_body, 0);
00493                 return 1;
00494             }
00495             debug("wap.deconvert",0,"WSP: Content convertion failed!");
00496             failed = 1;
00497         }
00498     }
00499     
00500     return (failed ? -1 : 0);
00501 }

Here is the call graph for this function:

Octstr * deconvert_multipart_formdata struct content content  )  [static]
 

Definition at line 1399 of file wap-appl.c.

References content::body, and mime_decompile().

01400 {
01401     Octstr *mime;
01402    
01403     if ((mime_decompile(content->body, &mime)) == 0)
01404         return mime;
01405 
01406     return NULL;
01407 }

Here is the call graph for this function:

void dev_null const char *  data,
size_t  len,
void *  context
[static]
 

Definition at line 1310 of file wap-appl.c.

01311 {
01312     /* nothing */
01313 }

Octstr* get_referer_url const WSPMachine sm  )  [static]
 

Definition at line 685 of file wap-appl.c.

References sm.

Referenced by return_reply().

00686 {
00687     return sm ? sm->referer_url : NULL;
00688 }

void indicate_push_abort WAPEvent e  )  [static]
 

Definition at line 1657 of file wap-appl.c.

References debug(), Po_PushAbort_Ind, WAPEvent::u, wap_event_create, and wap_push_ppg_dispatch_event().

Referenced by main_thread().

01658 {
01659     WAPEvent *ppg_event;
01660 
01661     ppg_event = wap_event_create(Po_PushAbort_Ind);
01662     ppg_event->u.Po_PushAbort_Ind.push_id = e->u.S_PushAbort_Ind.push_id;
01663     ppg_event->u.Po_PushAbort_Ind.reason = e->u.S_PushAbort_Ind.reason;
01664     ppg_event->u.Po_PushAbort_Ind.session_handle = 
01665         e->u.S_PushAbort_Ind.session_id;
01666 
01667     debug("wap.push.ota", 0, "OTA: making push abort indication for ppg");
01668     wap_push_ppg_dispatch_event(ppg_event);
01669 }

Here is the call graph for this function:

void indicate_push_connection WAPEvent e  )  [static]
 

Definition at line 1587 of file wap-appl.c.

References check_application_headers(), debug(), decode_bearer_indication(), gwlist_len(), http_create_empty_headers(), http_destroy_headers(), http_header_duplicate(), Pom_Connect_Ind, WAPEvent::u, wap_addr_tuple_duplicate(), wap_event_create, wap_push_ppg_dispatch_event(), and wsp_cap_duplicate_list().

Referenced by main_thread().

01588 {
01589     WAPEvent *ppg_event;
01590     List *push_headers, *application_headers, *bearer_headers;
01591 
01592     push_headers = http_header_duplicate(e->u.S_Connect_Ind.client_headers);
01593     application_headers = http_create_empty_headers();
01594     bearer_headers = http_create_empty_headers();
01595     
01596     ppg_event = wap_event_create(Pom_Connect_Ind);
01597     ppg_event->u.Pom_Connect_Ind.addr_tuple = 
01598         wap_addr_tuple_duplicate(e->u.S_Connect_Ind.addr_tuple);
01599     ppg_event->u.Pom_Connect_Ind.requested_capabilities = 
01600         wsp_cap_duplicate_list(e->u.S_Connect_Ind.requested_capabilities);
01601 
01602     check_application_headers(&push_headers, &application_headers);
01603     ppg_event->u.Pom_Connect_Ind.accept_application = application_headers;
01604 
01605     decode_bearer_indication(&push_headers, &bearer_headers);
01606 
01607     if (gwlist_len(bearer_headers) == 0) {
01608         http_destroy_headers(bearer_headers);
01609         ppg_event->u.Pom_Connect_Ind.bearer_indication = NULL;
01610     } else
01611         ppg_event->u.Pom_Connect_Ind.bearer_indication = bearer_headers;
01612 
01613     ppg_event->u.Pom_Connect_Ind.push_headers = push_headers;
01614     ppg_event->u.Pom_Connect_Ind.session_id = e->u.S_Connect_Ind.session_id;
01615     debug("wap.appl", 0, "APPL: making OTA connection indication to PPG");
01616 
01617     wap_push_ppg_dispatch_event(ppg_event);
01618 }

Here is the call graph for this function:

void indicate_push_disconnect WAPEvent e  )  [static]
 

Definition at line 1621 of file wap-appl.c.

References octstr_duplicate, Pom_Disconnect_Ind, WAPEvent::u, wap_event_create, and wap_push_ppg_dispatch_event().

Referenced by main_thread().

01622 {
01623     WAPEvent *ppg_event;
01624 
01625     ppg_event = wap_event_create(Pom_Disconnect_Ind);
01626     ppg_event->u.Pom_Disconnect_Ind.reason_code = 
01627         e->u.S_Disconnect_Ind.reason_code;
01628     ppg_event->u.Pom_Disconnect_Ind.error_headers =
01629         octstr_duplicate(e->u.S_Disconnect_Ind.error_headers);
01630     ppg_event->u.Pom_Disconnect_Ind.error_body =
01631         octstr_duplicate(e->u.S_Disconnect_Ind.error_body);
01632     ppg_event->u.Pom_Disconnect_Ind.session_handle =
01633         e->u.S_Disconnect_Ind.session_handle;
01634 
01635     wap_push_ppg_dispatch_event(ppg_event);
01636 }

Here is the call graph for this function:

void indicate_push_resume WAPEvent e  )  [static]
 

Definition at line 1688 of file wap-appl.c.

References decode_bearer_indication(), gwlist_len(), http_create_empty_headers(), http_destroy_headers(), http_header_duplicate(), Pom_Resume_Ind, WAPEvent::u, wap_addr_tuple_duplicate(), wap_event_create, and wap_push_ppg_dispatch_event().

Referenced by main_thread().

01689 {
01690     WAPEvent *ppg_event;
01691     List *push_headers, *bearer_headers;
01692 
01693     push_headers = http_header_duplicate(e->u.S_Resume_Ind.client_headers);
01694     bearer_headers = http_create_empty_headers();
01695     
01696     ppg_event = wap_event_create(Pom_Resume_Ind);
01697     ppg_event->u.Pom_Resume_Ind.addr_tuple = wap_addr_tuple_duplicate(
01698         e->u.S_Resume_Ind.addr_tuple);
01699    
01700     decode_bearer_indication(&push_headers, &bearer_headers);
01701 
01702     if (gwlist_len(bearer_headers) == 0) {
01703         http_destroy_headers(bearer_headers);
01704         ppg_event->u.Pom_Resume_Ind.bearer_indication = NULL;
01705     } else 
01706         ppg_event->u.Pom_Resume_Ind.bearer_indication = bearer_headers;
01707 
01708     ppg_event->u.Pom_Resume_Ind.client_headers = push_headers;
01709     ppg_event->u.Pom_Resume_Ind.session_id = e->u.S_Resume_Ind.session_id;
01710 
01711     wap_push_ppg_dispatch_event(ppg_event);
01712 }

Here is the call graph for this function:

void indicate_push_suspend WAPEvent e  )  [static]
 

Definition at line 1672 of file wap-appl.c.

References Pom_Suspend_Ind, WAPEvent::u, wap_event_create, and wap_push_ppg_dispatch_event().

Referenced by main_thread().

01673 {
01674     WAPEvent *ppg_event;
01675 
01676     ppg_event = wap_event_create(Pom_Suspend_Ind);
01677     ppg_event->u.Pom_Suspend_Ind.reason = e->u.S_Suspend_Ind.reason;
01678     ppg_event->u.Pom_Suspend_Ind.session_id =  e->u.S_Suspend_Ind.session_id;
01679 
01680     wap_push_ppg_dispatch_event(ppg_event);
01681 }

Here is the call graph for this function:

void main_thread void *   )  [static]
 

Definition at line 314 of file wap-appl.c.

References confirm_push(), gwlist_consume(), have_ppg, ind, indicate_push_abort(), indicate_push_connection(), indicate_push_disconnect(), indicate_push_resume(), indicate_push_suspend(), negotiate_capabilities(), panic, Pom_Connect_Res, queue, res, response_push_connection(), run_status, running, S_ConfirmedPush_Cnf, S_Connect_Ind, S_Connect_Res, S_Disconnect_Ind, S_MethodAbort_Ind, S_MethodInvoke_Ind, S_MethodInvoke_Res, S_MethodResult_Cnf, S_PushAbort_Ind, S_Resume_Ind, S_Resume_Res, S_Suspend_Ind, S_Unit_MethodInvoke_Ind, start_fetch(), WAPEvent::u, wap_event_create, wap_event_destroy(), wap_event_name(), wap_push_ppg_have_push_session_for(), wap_push_ppg_have_push_session_for_sid(), and wsp_session_dispatch_event().

Referenced by wap_appl_init(), and wap_appl_shutdown().

00315 {
00316     WAPEvent *ind, *res;
00317     long sid;
00318     WAPAddrTuple *tuple;
00319     
00320     while (run_status == running && (ind = gwlist_consume(queue)) != NULL) {
00321     switch (ind->type) {
00322     case S_MethodInvoke_Ind:
00323         res = wap_event_create(S_MethodInvoke_Res);
00324         res->u.S_MethodInvoke_Res.server_transaction_id =
00325             ind->u.S_MethodInvoke_Ind.server_transaction_id;
00326         res->u.S_MethodInvoke_Res.session_id =
00327         ind->u.S_MethodInvoke_Ind.session_id;
00328         wsp_session_dispatch_event(res);
00329         start_fetch(ind);
00330         break;
00331     
00332     case S_Unit_MethodInvoke_Ind:
00333         start_fetch(ind);
00334         break;
00335 
00336     case S_Connect_Ind:
00337         tuple  = ind->u.S_Connect_Ind.addr_tuple;
00338         if (have_ppg && wap_push_ppg_have_push_session_for(tuple)) {
00339             indicate_push_connection(ind);
00340         } else {
00341             res = wap_event_create(S_Connect_Res);
00342             /* FIXME: Not yet used by WSP layer */
00343             res->u.S_Connect_Res.server_headers = NULL;
00344             res->u.S_Connect_Res.negotiated_capabilities =
00345                 negotiate_capabilities(ind->u.S_Connect_Ind.requested_capabilities);
00346             res->u.S_Connect_Res.session_id = 
00347                    ind->u.S_Connect_Ind.session_id;
00348             wsp_session_dispatch_event(res);
00349         }
00350         wap_event_destroy(ind);
00351         break;
00352     
00353     case S_Disconnect_Ind:
00354         sid = ind->u.S_Disconnect_Ind.session_handle;
00355         if (have_ppg && wap_push_ppg_have_push_session_for_sid(sid)) 
00356             indicate_push_disconnect(ind);
00357         wap_event_destroy(ind);
00358         break;
00359 
00360     case S_Suspend_Ind:
00361         sid = ind->u.S_Suspend_Ind.session_id;
00362         if (have_ppg && wap_push_ppg_have_push_session_for_sid(sid)) 
00363             indicate_push_suspend(ind);
00364         wap_event_destroy(ind);
00365         break;
00366 
00367     case S_Resume_Ind:
00368         sid = ind->u.S_Resume_Ind.session_id;
00369         if (have_ppg && wap_push_ppg_have_push_session_for_sid(sid)) {
00370             indicate_push_resume(ind);
00371         } else {
00372             res = wap_event_create(S_Resume_Res);
00373             res->u.S_Resume_Res.server_headers = NULL;
00374             res->u.S_Resume_Res.session_id = ind->u.S_Resume_Ind.session_id;
00375             wsp_session_dispatch_event(res);
00376         }
00377         wap_event_destroy(ind);
00378         break;
00379     
00380     case S_MethodResult_Cnf:
00381         wap_event_destroy(ind);
00382         break;
00383 
00384     case S_ConfirmedPush_Cnf:
00385         confirm_push(ind);
00386         wap_event_destroy(ind);
00387         break;
00388     
00389     case S_MethodAbort_Ind:
00390         /* XXX Interrupt the fetch thread somehow */
00391         wap_event_destroy(ind);
00392         break;
00393 
00394     case S_PushAbort_Ind:
00395         indicate_push_abort(ind);
00396         wap_event_destroy(ind);
00397         break;
00398 
00399     case Pom_Connect_Res:
00400         response_push_connection(ind);
00401         wap_event_destroy(ind);
00402         break;
00403     
00404     default:
00405         panic(0, "WAP-APPL: Can't handle %s event", 
00406               wap_event_name(ind->type));
00407         break;
00408     } /* switch */
00409     } /* while */
00410 }

Here is the call graph for this function:

List * negotiate_capabilities List req_caps  )  [static]
 

Definition at line 1439 of file wap-appl.c.

References gwlist_create.

Referenced by main_thread().

01440 {
01441     /* Currently we don't know or care about any capabilities,
01442      * though it is likely that "Extended Methods" will be
01443      * the first. */
01444     return gwlist_create();
01445 }

void normalize_charset struct content content,
List device_headers
[static]
 

Definition at line 729 of file wap-appl.c.

References content::body, content::charset, charset, charset_convert(), debug(), find_charset_encoding(), http_charset_accepted(), octstr_case_compare(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_imm(), octstr_len(), and warning().

Referenced by return_reply().

00730 {
00731     Octstr* charset;
00732 
00733     if ((charset = find_charset_encoding(content->body)) == NULL) {
00734         if (octstr_len(content->charset) > 0) {
00735             charset = octstr_duplicate(content->charset);
00736         } else {
00737             charset = octstr_imm("UTF-8");
00738         }
00739     }
00740 
00741     debug("wap-appl",0,"Normalizing charset from %s", octstr_get_cstr(charset));
00742 
00743     if (octstr_case_compare(charset, octstr_imm("UTF-8")) != 0 &&
00744       !http_charset_accepted(device_headers, octstr_get_cstr(charset))) {
00745         if (!http_charset_accepted(device_headers, "UTF-8")) {
00746             warning(0, "WSP: Device doesn't support charset <%s> neither UTF-8",
00747               octstr_get_cstr(charset));
00748         } else {
00749             debug("wsp",0,"Converting wml/xhtml from charset <%s> to UTF-8",
00750               octstr_get_cstr(charset));
00751             if (charset_convert(content->body,
00752               octstr_get_cstr(charset), "UTF-8") >= 0) {
00753                 octstr_destroy(content->charset);
00754                 content->charset = octstr_create("UTF-8");
00755             }
00756         }
00757     }
00758     octstr_destroy(charset);
00759 }

Here is the call graph for this function:

void response_push_connection WAPEvent e  )  [static]
 

Definition at line 1719 of file wap-appl.c.

References debug(), gw_assert, Pom_Connect_Res, S_Connect_Res, WAPEvent::type, WAPEvent::u, wap_event_create, wsp_cap_duplicate_list(), wsp_event, and wsp_session_dispatch_event().

01720 {
01721     WAPEvent *wsp_event;
01722 
01723     gw_assert(e->type = Pom_Connect_Res);
01724 
01725     wsp_event = wap_event_create(S_Connect_Res);
01726     wsp_event->u.S_Connect_Res.session_id = e->u.Pom_Connect_Res.session_id;
01727     wsp_event->u.S_Connect_Res.negotiated_capabilities =
01728         wsp_cap_duplicate_list(e->u.Pom_Connect_Res.negotiated_capabilities);
01729     debug("wap.appl", 0, "APPL: making push connect response");
01730 
01731     wsp_session_dispatch_event(wsp_event);
01732 }

Here is the call graph for this function:

void return_replies_thread void *   )  [static]
 

Definition at line 1066 of file wap-appl.c.

References caller, request_data::client_SDU_size, request_data::event, http_destroy_headers(), http_receive_result, request_data::method, request_data::msisdn, octstr_destroy(), request_data::request_headers, return_reply(), run_status, request_data::session_id, request_data::url, wap_event_destroy(), and request_data::x_wap_tod.

Referenced by wap_appl_init(), and wap_appl_shutdown().

01067 {
01068     Octstr *body;
01069     struct request_data *p;
01070     int status;
01071     Octstr *final_url;
01072     List *headers;
01073 
01074     while (run_status == running) {
01075 
01076         p = http_receive_result(caller, &status, &final_url, &headers, &body);
01077         if (p == NULL)
01078             break;
01079 
01080         return_reply(status, body, headers, p->client_SDU_size,
01081                      p->event, p->session_id, p->method, p->url, p->x_wap_tod,
01082                      p->request_headers, p->msisdn);
01083 
01084         wap_event_destroy(p->event);
01085         http_destroy_headers(p->request_headers);
01086         octstr_destroy(p->msisdn);
01087         gw_free(p);
01088         octstr_destroy(final_url);
01089     }
01090 }

Here is the call graph for this function:

void return_reply int  status,
Octstr content_body,
List headers,
long  sdu_size,
WAPEvent orig_event,
long  session_id,
Octstr method,
Octstr url,
int  x_wap_tod,
List request_headers,
Octstr msisdn
[static]
 

Definition at line 764 of file wap-appl.c.

References add_x_wap_tod(), addr_tuple, WAPAddr::address, alog(), content::body, content::charset, convert_content(), counter_decrease(), debug(), device_home, error(), error_converting(), error_requesting(), error_requesting_back(), fetches, find_session_machine_by_id(), get_cookies(), get_referer_url(), gwlist_create, HTTP_BAD_GATEWAY, http_create_empty_headers(), http_destroy_headers(), http_header_combine(), http_header_get_content_type(), http_header_mark_transformation(), http_header_remove_all(), http_header_value(), http_remove_hop_headers(), http_status_class(), HTTP_STATUS_SUCCESSFUL, http_type_accepted(), normalize_charset(), octstr_compare(), octstr_create, octstr_destroy(), octstr_get_cstr, octstr_imm(), octstr_len(), octstr_search(), WAPAddrTuple::remote, return_session_reply(), return_unit_reply(), set_referer_url(), sm, WAPEvent::type, content::type, WAPEvent::u, content::url, content::version, and warning().

Referenced by return_replies_thread(), and start_fetch().

00768 {
00769     struct content content;
00770     int converted;
00771     WSPMachine *sm;
00772     List *device_headers, *t_headers;
00773     WAPAddrTuple *addr_tuple;
00774     Octstr *ua, *server;
00775 
00776     content.url = url;
00777     content.body = content_body;
00778     content.version = content.type = content.charset = NULL;
00779     server = ua = NULL;
00780 
00781     /* Get session machine for this session. If this was a connection-less
00782      * request be obviously will not find any session machine entry. */
00783     sm = find_session_machine_by_id(session_id);
00784 
00785     device_headers = gwlist_create();
00786 
00787     /* ensure we pass only the original headers to the convertion routine */
00788     t_headers = (orig_event->type == S_MethodInvoke_Ind) ?
00789         orig_event->u.S_MethodInvoke_Ind.session_headers :
00790         NULL;
00791     if (t_headers != NULL) http_header_combine(device_headers, t_headers);
00792     t_headers = (orig_event->type == S_MethodInvoke_Ind) ?
00793         orig_event->u.S_MethodInvoke_Ind.request_headers :
00794         orig_event->u.S_Unit_MethodInvoke_Ind.request_headers;
00795     if (t_headers != NULL) http_header_combine(device_headers, t_headers);
00796 
00797     /* 
00798      * We are acting as a proxy. Hence ensure we log a correct HTTP response
00799      * code to our access-log file to allow identification of failed proxying
00800      * requests in the main accesss-log.
00801      */
00802     /* get client IP and User-Agent identifier */
00803     addr_tuple = (orig_event->type == S_MethodInvoke_Ind) ?
00804         orig_event->u.S_MethodInvoke_Ind.addr_tuple : 
00805         orig_event->u.S_Unit_MethodInvoke_Ind.addr_tuple;
00806     ua = http_header_value(request_headers, octstr_imm("User-Agent"));
00807 
00808     if (headers != NULL) {
00809         /* get response content type and Server identifier */
00810         http_header_get_content_type(headers, &content.type, &content.charset);
00811         server = http_header_value(headers, octstr_imm("Server"));
00812     }
00813 
00814     /* log the access */
00815     /* XXX make this configurable in the future */
00816     alog("%s %s %s <%s> (%s, charset='%s') %ld %d <%s> <%s>", 
00817          octstr_get_cstr(addr_tuple->remote->address), 
00818          msisdn ? octstr_get_cstr(msisdn) : "-",         
00819          octstr_get_cstr(method), octstr_get_cstr(url), 
00820          content.type ? octstr_get_cstr(content.type) : "", 
00821          content.charset ? octstr_get_cstr(content.charset) : "",
00822          octstr_len(content.body), status < 0 ? HTTP_BAD_GATEWAY : status,
00823          ua ? octstr_get_cstr(ua) : "",
00824          server ? octstr_get_cstr(server) : "");
00825 
00826     octstr_destroy(ua);
00827     octstr_destroy(server);
00828     
00829 
00830     if (status < 0) {
00831         error(0, "WSP: HTTP lookup failed, oops.");
00832         /* smart WSP error messaging?! */
00833         if (wsp_smart_errors) {
00834             Octstr *referer_url;
00835             status = HTTP_OK;
00836             content.type = octstr_create("text/vnd.wap.wml");
00837             content.charset = octstr_create("");
00838             /*
00839              * check if a referer for this URL exists and 
00840              * get back to the previous page in this case
00841              */
00842             if ((referer_url = get_referer_url(find_session_machine_by_id(session_id)))) {
00843                 content.body = error_requesting_back(url, referer_url);
00844                 debug("wap.wsp",0,"WSP: returning smart error WML deck for referer URL");
00845             } 
00846             /*
00847              * if there is no referer to retun to, check if we have a
00848              * device-home defined and return to that, otherwise simply
00849              * drop an error wml deck.
00850              */
00851             else if (device_home != NULL) {
00852                 content.body = error_requesting_back(url, device_home);
00853                 debug("wap.wsp",0,"WSP: returning smart error WML deck for device-home URL");
00854             } else {
00855                 content.body = error_requesting(url);
00856                 debug("wap.wsp",0,"WSP: returning smart error WML deck");
00857             }
00858 
00859             /* 
00860              * if we did not connect at all there is no content in 
00861              * the headers list, so create for the upcoming transformation
00862              */
00863             if (headers == NULL)
00864                 headers = http_create_empty_headers();
00865 
00866             converted = convert_content(&content, device_headers, 0);
00867             if (converted == 1)
00868                 http_header_mark_transformation(headers, content.body, content.type);
00869 
00870         } else {
00871             /* no WSP smart error messaging */
00872             status = HTTP_BAD_GATEWAY;
00873             content.type = octstr_create("text/plain");
00874             content.charset = octstr_create("");
00875             content.body = octstr_create("");
00876         }
00877 
00878     } else {
00879         /* received response by HTTP server */
00880  
00881 #ifdef ENABLE_COOKIES
00882         if (session_id != -1)
00883             if (get_cookies(headers, find_session_machine_by_id(session_id)) == -1)
00884                 error(0, "WSP: Failed to extract cookies");
00885 #endif
00886 
00887         /* 
00888          * XXX why do we transcode charsets on the content body here?!
00889          * Why is this not in the scope of the HTTP server, rather
00890          * then doing this inside Kannel?! st. 
00891          */
00892 
00893         /* 
00894          * Adapts content body's charset to device.
00895          * If device doesn't support body's charset but supports UTF-8, this 
00896          * block tries to convert body to UTF-8. 
00897          * (This is required for Sharp GX20 for example)
00898          */
00899         if (octstr_search(content.type, octstr_imm("text/vnd.wap.wml"), 0) >= 0 || 
00900             octstr_search(content.type, octstr_imm("application/xhtml+xml"), 0) >= 0 ||
00901             octstr_search(content.type, octstr_imm("application/vnd.wap.xhtml+xml"), 0) >= 0) {
00902 
00903             normalize_charset(&content, device_headers);
00904         }
00905 
00906         /* set WBXML Encoding-Version for wml->wmlc conversion */
00907         if (sm != NULL) {
00908             content.version = http_header_value(sm->http_headers, 
00909                                                 octstr_imm("Encoding-Version"));
00910         } else {
00911             content.version = NULL;
00912         }
00913 
00914         /* convert content-type by our own converter table */
00915         converted = convert_content(&content, device_headers, 
00916                                     octstr_compare(method, octstr_imm("HEAD")) == 0);
00917         if (converted < 0) {
00918             warning(0, "WSP: All converters for `%s' at `%s' failed.",
00919                     octstr_get_cstr(content.type), octstr_get_cstr(url));
00920 
00921             /* 
00922              * Don't change status; just send the client what we did get.
00923              * Or if smart error messages are configured, send a wmlc deck
00924              * with accurate information.
00925              */
00926             if (wsp_smart_errors) {
00927                 octstr_destroy(content.body);
00928                 octstr_destroy(content.charset);
00929                 content.body = error_converting(url, content.type);
00930                 content.charset = octstr_create("UTF-8");
00931                 
00932                 debug("wap.wsp",0,"WSP: returning smart error WML deck for failed converters");
00933 
00934                 converted = convert_content(&content, device_headers, 0);
00935                 if (converted == 1)
00936                     http_header_mark_transformation(headers, content.body, content.type);
00937 
00938             }
00939         }
00940         else if (converted == 1) {
00941             http_header_mark_transformation(headers, content.body, content.type);
00942 
00943             /* 
00944              * set referer URL to WSPMachine, but only if this was a converted
00945              * content-type, like .wml
00946              */
00947             if (session_id != -1) {
00948                 debug("wap.wsp.http",0,"WSP: Setting Referer URL to <%s>", 
00949                       octstr_get_cstr(url));
00950                 if ((sm = find_session_machine_by_id(session_id)) != NULL) {
00951                     set_referer_url(url, sm);
00952                 } else {
00953                     error(0,"WSP: Failed to find session machine for ID %ld",
00954                           session_id);
00955                 }
00956             }
00957         }
00958 
00959         /* if converted == 0 then we pass the content wihtout modification */
00960     }
00961 
00962     if (headers == NULL)
00963         headers = http_create_empty_headers();
00964     http_remove_hop_headers(headers);
00965     http_header_remove_all(headers, "X-WAP.TOD");
00966     if (x_wap_tod)
00967         add_x_wap_tod(headers);
00968 
00969     if (content.body == NULL)
00970         content.body = octstr_create("");
00971    
00972     /*
00973      * Deal with otherwise wap-aware servers that return text/html error
00974      * messages if they report an error.
00975      * (Normally we leave the content type alone even if the client doesn't
00976      * claim to accept it, because the server might know better than the
00977      * gateway.)
00978      */
00979     if (http_status_class(status) != HTTP_STATUS_SUCCESSFUL &&
00980         !http_type_accepted(request_headers, octstr_get_cstr(content.type))) {
00981         warning(0, "WSP: Content type <%s> not supported by client,"
00982                    " deleting body.", octstr_get_cstr(content.type));
00983         octstr_destroy(content.body);
00984         content.body = octstr_create("");
00985         octstr_destroy(content.type);
00986         content.type = octstr_create("text/plain");
00987         http_header_mark_transformation(headers, content.body, content.type);
00988     }
00989     /* remove body if request method was HEAD, we act strictly here */
00990     else if (octstr_compare(method, octstr_imm("HEAD")) == 0) {
00991         octstr_destroy(content.body);
00992         content.body = octstr_create("");
00993         /* change to text/plain if received content-type is not accepted */
00994         if (!http_type_accepted(request_headers, "*/*") &&
00995             !http_type_accepted(request_headers, octstr_get_cstr(content.type))) {
00996             octstr_destroy(content.type);
00997             content.type = octstr_create("text/plain");
00998         }
00999         debug("wsp",0,"WSP: HEAD request, removing body, content-type is now <%s>", 
01000               octstr_get_cstr(content.type));
01001         http_header_mark_transformation(headers, content.body, content.type);
01002     }
01003 
01004 #ifdef ENABLE_NOT_ACCEPTED 
01005     /* Returns HTTP response 406 if content-type is not supported by device */
01006     else if (request_headers && content.type &&
01007              !http_type_accepted(request_headers, octstr_get_cstr(content.type)) &&
01008              !http_type_accepted(request_headers, "*/*")) {
01009         warning(0, "WSP: content-type <%s> not supported", 
01010                 octstr_get_cstr(content.type));
01011         status = HTTP_NOT_ACCEPTABLE;
01012         octstr_destroy(content.type);
01013         content.type = octstr_create("text/plain");
01014         octstr_destroy(content.charset);
01015         octstr_destroy(content.body);
01016         content.charset = octstr_create("");
01017         content.body = octstr_create("");
01018         http_header_mark_transformation(headers, content.body, content.type);
01019     }
01020 #endif
01021 
01022     /*
01023      * If the response is too large to be sent to the client,
01024      * suppress it and inform the client.
01025      */
01026     if (octstr_len(content.body) > sdu_size && sdu_size > 0) {
01027         /*
01028          * Only change the status if it indicated success.
01029          * If it indicated an error, then that information is
01030          * more useful to the client than our "Bad Gateway" would be.
01031          * The too-large body is probably an error page in html.
01032          */
01033         /* XXX add WSP smart messaging here too */
01034         if (http_status_class(status) == HTTP_STATUS_SUCCESSFUL)
01035             status = HTTP_BAD_GATEWAY;
01036         warning(0, "WSP: Entity at %s too large (size %ld B, limit %lu B)",
01037                 octstr_get_cstr(url), octstr_len(content.body), sdu_size);
01038         octstr_destroy(content.body);
01039         content.body = octstr_create("");
01040         http_header_mark_transformation(headers, content.body, content.type);
01041     }
01042 
01043     if (orig_event->type == S_MethodInvoke_Ind) {
01044         return_session_reply(orig_event->u.S_MethodInvoke_Ind.server_transaction_id,
01045                              status, headers, content.body, session_id);
01046     } else {
01047         return_unit_reply(orig_event->u.S_Unit_MethodInvoke_Ind.addr_tuple,
01048                           orig_event->u.S_Unit_MethodInvoke_Ind.transaction_id,
01049                           status, headers, content.body);
01050     }
01051 
01052     octstr_destroy(content.version); /* body was re-used above */
01053     octstr_destroy(content.type); /* body was re-used above */
01054     octstr_destroy(content.charset);
01055     octstr_destroy(url);          /* same as content.url */
01056     http_destroy_headers(device_headers);
01057 
01058     counter_decrease(fetches);
01059 }

Here is the call graph for this function:

void return_session_reply long  server_transaction_id,
long  status,
List headers,
Octstr body,
long  session_id
[static]
 

Definition at line 694 of file wap-appl.c.

References S_MethodResult_Req, WAPEvent::u, wap_event_create, and wsp_session_dispatch_event().

Referenced by return_reply().

00696 {
00697     WAPEvent *e;
00698     
00699     e = wap_event_create(S_MethodResult_Req);
00700     e->u.S_MethodResult_Req.server_transaction_id = server_transaction_id;
00701     e->u.S_MethodResult_Req.status = status;
00702     e->u.S_MethodResult_Req.response_headers = headers;
00703     e->u.S_MethodResult_Req.response_body = body;
00704     e->u.S_MethodResult_Req.session_id = session_id;
00705     wsp_session_dispatch_event(e);
00706 }

Here is the call graph for this function:

void return_unit_reply WAPAddrTuple tuple,
long  transaction_id,
long  status,
List headers,
Octstr body
[static]
 

Definition at line 713 of file wap-appl.c.

References S_Unit_MethodResult_Req, WAPEvent::u, wap_addr_tuple_duplicate(), wap_event_create, and wsp_unit_dispatch_event().

Referenced by return_reply().

00715 {
00716     WAPEvent *e;
00717 
00718     e = wap_event_create(S_Unit_MethodResult_Req);
00719     e->u.S_Unit_MethodResult_Req.addr_tuple = 
00720         wap_addr_tuple_duplicate(tuple);
00721     e->u.S_Unit_MethodResult_Req.transaction_id = transaction_id;
00722     e->u.S_Unit_MethodResult_Req.status = status;
00723     e->u.S_Unit_MethodResult_Req.response_headers = headers;
00724     e->u.S_Unit_MethodResult_Req.response_body = body;
00725     wsp_unit_dispatch_event(e);
00726 }

Here is the call graph for this function:

void set_referer_url Octstr url,
WSPMachine sm
[static]
 

Definition at line 675 of file wap-appl.c.

References gw_assert, octstr_destroy(), octstr_duplicate, and sm.

Referenced by return_reply().

00676 {
00677     gw_assert(url != NULL);
00678     gw_assert(sm != NULL);
00679 
00680     octstr_destroy(sm->referer_url);
00681     sm->referer_url = octstr_duplicate(url);
00682 }

Here is the call graph for this function:

void split_header_list List **  headers,
List **  new_headers,
char *  name
[static]
 

Definition at line 1573 of file wap-appl.c.

References http_header_find_all(), http_header_remove_all(), and name.

Referenced by check_application_headers(), and decode_bearer_indication().

01574 {
01575     if (*headers == NULL)
01576         return;
01577 
01578     *new_headers = http_header_find_all(*headers, name);
01579     http_header_remove_all(*headers, name);  
01580 }

Here is the call graph for this function:

void start_fetch WAPEvent  )  [static]
 

Definition at line 1103 of file wap-appl.c.

References add_accept_headers(), add_charset_headers(), add_client_sdu_size(), add_kannel_version(), add_msisdn(), add_network_info(), add_session_id(), add_via(), addr_tuple, WAPAddr::address, content::body, caller, content::charset, request_data::client_SDU_size, counter_increase(), deconvert_content(), error(), request_data::event, event, fetches, find_session_machine_by_id(), gwlist_create, HEALTH_DECK, http_create_empty_headers(), http_destroy_headers(), http_header_add(), http_header_combine(), http_header_get_content_type(), http_header_mark_transformation(), http_header_pack(), http_header_remove_all(), http_name2method(), http_remove_hop_headers(), http_start_request(), info(), octstr_compare(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_imm(), octstr_len(), octstr_str_compare(), WAPAddr::port, radius_acct_get_msisdn(), WAPAddrTuple::remote, return_reply(), S_MethodInvoke_Ind, S_Unit_MethodInvoke_Ind, set_cookies(), content::type, WAPEvent::type, WAPEvent::u, wap_event_destroy(), and wap_map_url().

Referenced by main_thread().

01104 {
01105     int ret;
01106     long client_SDU_size; /* 0 means no limit */
01107     Octstr *url;
01108     List *session_headers;
01109     List *request_headers;
01110     List *actual_headers;
01111     List *resp_headers;
01112     WAPAddrTuple *addr_tuple;
01113     long session_id;
01114     Octstr *content_body;
01115     Octstr *method;     /* type of request, normally a get or a post */
01116     Octstr *request_body;
01117     int x_wap_tod;          /* X-WAP.TOD header was present in request */
01118     Octstr *magic_url;
01119     struct request_data *p;
01120     Octstr *send_msisdn_query, *send_msisdn_header, *send_msisdn_format;
01121     int accept_cookies;
01122     Octstr *msisdn;
01123     
01124     counter_increase(fetches);
01125     
01126     if (event->type == S_MethodInvoke_Ind) {
01127         struct S_MethodInvoke_Ind *p;
01128     
01129         /* WSP, connection orientated */
01130         p = &event->u.S_MethodInvoke_Ind;
01131         session_headers = p->session_headers;
01132         request_headers = p->request_headers;
01133         url = octstr_duplicate(p->request_uri);
01134         addr_tuple = p->addr_tuple;
01135         session_id = p->session_id;
01136         client_SDU_size = p->client_SDU_size;
01137         request_body = octstr_duplicate(p->request_body);
01138         method = p->method;
01139     } else {
01140         struct S_Unit_MethodInvoke_Ind *p;
01141     
01142         /* WDP, non orientated */
01143         p = &event->u.S_Unit_MethodInvoke_Ind;
01144         session_headers = NULL;
01145         request_headers = p->request_headers;
01146         url = octstr_duplicate(p->request_uri);
01147         addr_tuple = p->addr_tuple;
01148         session_id = -1;
01149         client_SDU_size = 0; /* No limit */
01150         request_body = octstr_duplicate(p->request_body);
01151         method = p->method;
01152     }
01153 
01154     msisdn = radius_acct_get_msisdn(addr_tuple->remote->address);
01155     info(0, "Fetching URL <%s> for MSISDN <%s>, IP <%s:%ld>", octstr_get_cstr(url),
01156          msisdn ? octstr_get_cstr(msisdn) : "", 
01157          addr_tuple->remote->address ? octstr_get_cstr(addr_tuple->remote->address) : "",
01158          addr_tuple->remote->port);
01159 
01160     /* 
01161      * XXX this URL mapping needs to be rebuild! st. 
01162      */
01163 
01164     /* try to rewrite URL */
01165     wap_map_url(&url, &send_msisdn_query, &send_msisdn_header,
01166                 &send_msisdn_format, &accept_cookies);
01167     /* if no mapping found, then use our RADIUS acct proxy header */
01168     if (send_msisdn_header == NULL)
01169         send_msisdn_header = octstr_create("X-WAP-Network-Client-MSISDN");
01170 
01171     actual_headers = gwlist_create();
01172     
01173     if (session_headers != NULL)
01174         http_header_combine(actual_headers, session_headers);
01175     if (request_headers != NULL)
01176         http_header_combine(actual_headers, request_headers);
01177     
01178     x_wap_tod = http_header_remove_all(actual_headers, "X-WAP.TOD");
01179     add_accept_headers(actual_headers);
01180     add_charset_headers(actual_headers);
01181     add_network_info(actual_headers, addr_tuple);
01182     add_client_sdu_size(actual_headers, client_SDU_size);
01183     add_via(actual_headers);
01184 
01185 #ifdef ENABLE_COOKIES
01186     /* DAVI: to finish - accept_cookies -1, 
01187      * use global accept-cookies, 0 = no, 1 = yes ? */
01188     if (accept_cookies != 0 && (session_id != -1) &&  
01189         /* DAVI (set_cookies(url, actual_headers, 
01190                              find_session_machine_by_id(session_id)) == -1)) */
01191         (set_cookies(actual_headers, find_session_machine_by_id(session_id)) == -1)) 
01192         error(0, "WSP: Failed to add cookies");
01193 #endif
01194 
01195     /* set referer URL to HTTP header from WSPMachine */
01196     /* 
01197      * XXX This makes Open Group's test suite wml/events/tasks/go/5 failing, 
01198      * which requires that device is *not* sending referer, but Kannel drops
01199      * it in. We have to remove this for now.
01200      */
01201     /*
01202     if (session_id != -1) {
01203         if ((referer_url = get_referer_url(find_session_machine_by_id(session_id))) != NULL) {
01204             add_referer_url(actual_headers, referer_url);
01205         }
01206     }
01207     */
01208     
01209     add_kannel_version(actual_headers);
01210     add_session_id(actual_headers, session_id);
01211 
01212     add_msisdn(actual_headers, addr_tuple, send_msisdn_header);
01213     octstr_destroy(send_msisdn_query);
01214     octstr_destroy(send_msisdn_header);
01215     octstr_destroy(send_msisdn_format);
01216     
01217     http_remove_hop_headers(actual_headers);
01218     http_header_pack(actual_headers);
01219     
01220     magic_url = octstr_imm("kannel:alive");
01221 
01222     /* check if this request is a call for our magic URL */
01223     if (octstr_str_compare(method, "GET")  == 0 && 
01224         octstr_compare(url, magic_url) == 0) {
01225         ret = HTTP_OK;
01226         resp_headers = gwlist_create();
01227         http_header_add(resp_headers, "Content-Type", "text/vnd.wap.wml");
01228         content_body = octstr_create(HEALTH_DECK);
01229         octstr_destroy(request_body);
01230         return_reply(ret, content_body, resp_headers, client_SDU_size,
01231                      event, session_id, method, url, x_wap_tod, actual_headers,
01232                      msisdn);
01233         wap_event_destroy(event);
01234         http_destroy_headers(actual_headers);
01235         octstr_destroy(msisdn);
01236     } 
01237     /* otherwise it should be a GET, POST or HEAD request type */
01238     else if (octstr_str_compare(method, "GET") == 0 ||
01239              octstr_str_compare(method, "POST") == 0 ||
01240              octstr_str_compare(method, "HEAD") == 0) {
01241 
01242         /* we don't allow a body within a GET or HEAD request */
01243         if (request_body != NULL && (octstr_str_compare(method, "GET") == 0 ||
01244                                      octstr_str_compare(method, "HEAD") == 0)) {
01245             octstr_destroy(request_body);
01246             request_body = NULL;
01247         }
01248 
01249         /* 
01250          * Call deconvert_content() here for transformations of binary
01251          * encoded POST requests from the client into plain text decoded
01252          * POST requests for the HTTP server.
01253          * Mainly this is used for multipart/form-data transmissions,
01254          * including MMS on-the-fly message decoding.
01255          * When we are doing mms, the phone POSTs contents and acknowled-
01256          * gements. In this case, we dont do not deconvert anything.
01257          */
01258         if (octstr_str_compare(method, "POST") == 0 && request_body && 
01259             octstr_len(request_body)) {
01260             struct content content;
01261             int converted;
01262 
01263             http_header_get_content_type(actual_headers, &content.type, 
01264                                          &content.charset);
01265             content.body = request_body;
01266             converted = deconvert_content(&content); 
01267             if (converted == 1) 
01268                 http_header_mark_transformation(actual_headers, content.body, 
01269                                                 content.type);
01270             request_body = content.body;
01271             octstr_destroy(content.type);
01272             octstr_destroy(content.charset);
01273         }
01274 
01275         /* struct that is used for the HTTP response identifier */
01276         p = gw_malloc(sizeof(*p));
01277         p->client_SDU_size = client_SDU_size;
01278         p->event = event;
01279         p->session_id = session_id;
01280         p->method = method;
01281         p->url = url;
01282         p->x_wap_tod = x_wap_tod;
01283         p->request_headers = actual_headers;
01284         p->msisdn = msisdn;
01285 
01286         /* issue the request to the HTTP server */
01287         http_start_request(caller, http_name2method(method), url, actual_headers, 
01288                            request_body, 0, p, NULL);
01289 
01290         octstr_destroy(request_body);
01291     } 
01292     /* we don't support the WSP/HTTP method the client asked us */
01293     else {
01294         error(0, "WSP: Method %s not supported.", octstr_get_cstr(method));
01295         content_body = octstr_create("");
01296         resp_headers = http_create_empty_headers();
01297         ret = HTTP_NOT_IMPLEMENTED;
01298         octstr_destroy(request_body);
01299         return_reply(ret, content_body, resp_headers, client_SDU_size,
01300                      event, session_id, method, url, x_wap_tod, actual_headers,
01301                      msisdn);
01302         wap_event_destroy(event);
01303         http_destroy_headers(actual_headers);
01304         octstr_destroy(msisdn);
01305     }
01306 }

Here is the call graph for this function:

void wap_appl_dispatch WAPEvent event  ) 
 

Definition at line 288 of file wap-appl.c.

References event, gw_assert, gwlist_produce(), queue, run_status, and running.

Referenced by main().

00289 {
00290     gw_assert(run_status == running);
00291     gwlist_produce(queue, event);
00292 }

Here is the call graph for this function:

long wap_appl_get_load void   ) 
 

Definition at line 295 of file wap-appl.c.

References counter_value(), fetches, gw_assert, gwlist_len(), queue, run_status, and running.

Referenced by main().

00296 {
00297     gw_assert(run_status == running);
00298     return counter_value(fetches) + gwlist_len(queue);
00299 }

Here is the call graph for this function:

void wap_appl_init Cfg cfg  ) 
 

Definition at line 249 of file wap-appl.c.

References caller, charsets, counter_create(), fetches, gw_assert, gwlist_add_producer(), gwlist_create, gwthread_create, have_ppg, http_caller_create(), limbo, main_thread(), queue, return_replies_thread(), run_status, and wml_charsets().

Referenced by main().

00250 {
00251     gw_assert(run_status == limbo);
00252     queue = gwlist_create();
00253     fetches = counter_create();
00254     gwlist_add_producer(queue);
00255     run_status = running;
00256     charsets = wml_charsets();
00257     caller = http_caller_create();
00258     gwthread_create(main_thread, NULL);
00259     gwthread_create(return_replies_thread, NULL);
00260 
00261     if (cfg != NULL)
00262         have_ppg = 1;
00263     else
00264         have_ppg = 0;
00265 }

Here is the call graph for this function:

void wap_appl_shutdown void   ) 
 

Definition at line 268 of file wap-appl.c.

References caller, charsets, counter_destroy(), fetches, gw_assert, gwlist_destroy(), gwlist_remove_producer(), gwthread_join_every(), http_caller_destroy(), http_caller_signal_shutdown(), main_thread(), octstr_destroy_item(), queue, return_replies_thread(), run_status, running, wap_event_destroy_item(), wap_map_destroy(), and wap_map_user_destroy().

Referenced by main().

00269 {
00270     gw_assert(run_status == running);
00271     run_status = terminating;
00272     
00273     gwlist_remove_producer(queue);
00274     gwthread_join_every(main_thread);
00275     
00276     http_caller_signal_shutdown(caller);
00277     gwthread_join_every(return_replies_thread);
00278     
00279     wap_map_destroy(); 
00280     wap_map_user_destroy(); 
00281     http_caller_destroy(caller);
00282     gwlist_destroy(queue, wap_event_destroy_item);
00283     gwlist_destroy(charsets, octstr_destroy_item);
00284     counter_destroy(fetches);
00285 }

Here is the call graph for this function:


Variable Documentation

HTTPCaller* caller = NULL [static]
 

Definition at line 129 of file wap-appl.c.

Referenced by return_replies_thread(), start_fetch(), wap_appl_init(), and wap_appl_shutdown().

List* charsets = NULL [static]
 

Definition at line 141 of file wap-appl.c.

Referenced by wap_appl_init(), and wap_appl_shutdown().

Octstr*(* convert)(struct content *)
 

struct { ... } converters[] [static]
 

Referenced by add_accept_headers(), and convert_content().

Octstr*(* deconvert)(struct content *)
 

struct { ... } deconverters[] [static]
 

Referenced by deconvert_content().

Octstr* device_home
 

Definition at line 112 of file wapbox.c.

Referenced by config_reload(), main(), and return_reply().

Counter* fetches = NULL [static]
 

Definition at line 135 of file wap-appl.c.

Referenced by return_reply(), start_fetch(), wap_appl_get_load(), wap_appl_init(), and wap_appl_shutdown().

int have_ppg = 0 [static]
 

Definition at line 176 of file wap-appl.c.

Referenced by main_thread(), and wap_appl_init().

List* queue = NULL [static]
 

Definition at line 123 of file wap-appl.c.

Referenced by main_thread(), wap_appl_dispatch(), wap_appl_get_load(), wap_appl_init(), and wap_appl_shutdown().

char* result_type
 

Definition at line 216 of file wap-appl.c.

Referenced by add_accept_headers(), convert_content(), deconvert_content(), and pap_convert_content().

enum { ... } run_status [static]
 

Referenced by main_thread(), return_replies_thread(), wap_appl_dispatch(), wap_appl_get_load(), wap_appl_init(), and wap_appl_shutdown().

char* type
 

Definition at line 215 of file wap-appl.c.

int wsp_smart_errors
 

Definition at line 111 of file wapbox.c.

Referenced by config_reload().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.