00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #include <string.h>
00086
00087 #include "gwlib/gwlib.h"
00088 #include "wmlscript/ws.h"
00089 #include "xml_shared.h"
00090 #include "wml_compiler.h"
00091 #include "mime_decompiler.h"
00092 #include "wap/wap.h"
00093 #include "wap-appl.h"
00094 #include "wap_push_ppg.h"
00095 #include "wap/wsp_strings.h"
00096 #include "wap/wsp_caps.h"
00097 #include "wap/wsp.h"
00098 #ifdef ENABLE_COOKIES
00099 #include "wap/cookies.h"
00100 #endif
00101 #include "radius/radius_acct.h"
00102 #include "wap-error.h"
00103 #include "wap-maps.h"
00104
00105 #define ENABLE_NOT_ACCEPTED
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 static enum { limbo, running, terminating } run_status = limbo;
00118
00119
00120
00121
00122
00123 static List *queue = NULL;
00124
00125
00126
00127
00128
00129 static HTTPCaller *caller = NULL;
00130
00131
00132
00133
00134
00135 static Counter *fetches = NULL;
00136
00137
00138
00139
00140
00141 static List *charsets = NULL;
00142
00143 struct content {
00144 Octstr *body;
00145 Octstr *type;
00146 Octstr *charset;
00147 Octstr *url;
00148 Octstr *version;
00149 };
00150
00151
00152
00153
00154
00155 struct request_data {
00156 long client_SDU_size;
00157 WAPEvent *event;
00158 long session_id;
00159 Octstr *method;
00160 Octstr *url;
00161 long x_wap_tod;
00162 List *request_headers;
00163 Octstr *msisdn;
00164 };
00165
00166
00167
00168
00169
00170 extern int wsp_smart_errors;
00171 extern Octstr *device_home;
00172
00173
00174
00175
00176 static int have_ppg = 0;
00177
00178
00179
00180
00181
00182 static void main_thread(void *);
00183 static void start_fetch(WAPEvent *);
00184 static void return_replies_thread(void *);
00185
00186 static void dev_null(const char *data, size_t len, void *context);
00187
00188 static Octstr *convert_wml_to_wmlc(struct content *content);
00189 static Octstr *convert_wmlscript_to_wmlscriptc(struct content *content);
00190
00191 static Octstr *deconvert_multipart_formdata(struct content *content);
00192
00193 static List *negotiate_capabilities(List *req_caps);
00194
00195 static struct {
00196 char *type;
00197 char *result_type;
00198 Octstr *(*convert)(struct content *);
00199 } converters[] = {
00200 { "text/vnd.wap.wml",
00201 "application/vnd.wap.wmlc",
00202 convert_wml_to_wmlc },
00203 { "text/vnd.wap.wmlscript",
00204 "application/vnd.wap.wmlscriptc",
00205 convert_wmlscript_to_wmlscriptc },
00206
00207
00208
00209
00210
00211 };
00212 #define NUM_CONVERTERS ((long)(sizeof(converters) / sizeof(converters[0])))
00213
00214 static struct {
00215 char *type;
00216 char *result_type;
00217 Octstr *(*deconvert)(struct content *);
00218 } deconverters[] = {
00219 { "application/vnd.wap.multipart.form-data",
00220 "multipart/form-data; boundary=kannel_boundary",
00221 deconvert_multipart_formdata },
00222
00223
00224
00225
00226
00227 };
00228 #define NUM_DECONVERTERS ((long)(sizeof(deconverters) / sizeof(deconverters[0])))
00229
00230
00231
00232
00233
00234 static void indicate_push_connection(WAPEvent *e);
00235 static void indicate_push_disconnect(WAPEvent *e);
00236 static void indicate_push_suspend(WAPEvent *e);
00237 static void indicate_push_resume(WAPEvent *e);
00238 static void confirm_push(WAPEvent *e);
00239 static void indicate_push_abort(WAPEvent *e);
00240 static void split_header_list(List **headers, List **new_headers, char *name);
00241 static void check_application_headers(List **headers, List **app_headers);
00242 static void decode_bearer_indication(List **headers, List **bearer_headers);
00243 static void response_push_connection(WAPEvent *e);
00244
00245
00246
00247
00248
00249 void wap_appl_init(Cfg *cfg)
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 }
00266
00267
00268 void wap_appl_shutdown(void)
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 }
00286
00287
00288 void wap_appl_dispatch(WAPEvent *event)
00289 {
00290 gw_assert(run_status == running);
00291 gwlist_produce(queue, event);
00292 }
00293
00294
00295 long wap_appl_get_load(void)
00296 {
00297 gw_assert(run_status == running);
00298 return counter_value(fetches) + gwlist_len(queue);
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 static void main_thread(void *arg)
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
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
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 }
00409 }
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 static int convert_content(struct content *content, List *request_headers,
00422 int allow_empty)
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
00435
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 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 static int deconvert_content(struct content *content)
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 }
00502
00503
00504
00505 static void add_kannel_version(List *headers)
00506 {
00507 http_header_add(headers, "X-WAP-Gateway", GW_NAME "/" GW_VERSION);
00508 }
00509
00510
00511
00512
00513
00514
00515 static void add_charset_headers(List *headers)
00516 {
00517 if (!http_charset_accepted(headers, "utf-8"))
00518 http_header_add(headers, "Accept-Charset", "utf-8");
00519 }
00520
00521
00522
00523 static void add_accept_headers(List *headers)
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 }
00535
00536
00537
00538 static void add_network_info(List *headers, WAPAddrTuple *addr_tuple)
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 }
00545
00546
00547
00548 static void add_session_id(List *headers, long session_id)
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 }
00556
00557
00558
00559 static void add_client_sdu_size(List *headers, long sdu_size)
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 }
00569
00570
00571 static void add_via(List *headers)
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 }
00584
00585
00586
00587
00588
00589
00590
00591
00592 static void add_x_wap_tod(List *headers)
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 }
00605
00606
00607
00608 static void add_msisdn(List *headers, WAPAddrTuple *addr_tuple,
00609 Octstr *send_msisdn_header)
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
00619
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
00630
00631
00632
00633
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 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675 static void set_referer_url(Octstr *url, WSPMachine *sm)
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 }
00683
00684
00685 static Octstr *get_referer_url(const WSPMachine *sm)
00686 {
00687 return sm ? sm->referer_url : NULL;
00688 }
00689
00690
00691
00692
00693
00694 static void return_session_reply(long server_transaction_id, long status,
00695 List *headers, Octstr *body, long session_id)
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 }
00707
00708
00709
00710
00711
00712
00713 static void return_unit_reply(WAPAddrTuple *tuple, long transaction_id,
00714 long status, List *headers, Octstr *body)
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 }
00727
00728
00729 static void normalize_charset(struct content * content, List* device_headers)
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 }
00760
00761
00762
00763
00764 static void return_reply(int status, Octstr *content_body, List *headers,
00765 long sdu_size, WAPEvent *orig_event, long session_id,
00766 Octstr *method, Octstr *url, int x_wap_tod,
00767 List *request_headers, Octstr *msisdn)
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
00782
00783 sm = find_session_machine_by_id(session_id);
00784
00785 device_headers = gwlist_create();
00786
00787
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
00799
00800
00801
00802
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
00810 http_header_get_content_type(headers, &content.type, &content.charset);
00811 server = http_header_value(headers, octstr_imm("Server"));
00812 }
00813
00814
00815
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
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
00840
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
00848
00849
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
00861
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
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
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
00889
00890
00891
00892
00893
00894
00895
00896
00897
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
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
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
00923
00924
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
00945
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
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
00974
00975
00976
00977
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
00990 else if (octstr_compare(method, octstr_imm("HEAD")) == 0) {
00991 octstr_destroy(content.body);
00992 content.body = octstr_create("");
00993
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
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
01024
01025
01026 if (octstr_len(content.body) > sdu_size && sdu_size > 0) {
01027
01028
01029
01030
01031
01032
01033
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);
01053 octstr_destroy(content.type);
01054 octstr_destroy(content.charset);
01055 octstr_destroy(url);
01056 http_destroy_headers(device_headers);
01057
01058 counter_decrease(fetches);
01059 }
01060
01061
01062
01063
01064
01065
01066 static void return_replies_thread(void *arg)
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 }
01091
01092
01093
01094
01095
01096
01097 #define HEALTH_DECK \
01098 "<?xml version=\"1.0\"?>" \
01099 "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD 1.1//EN\" " \
01100 "\"http://www.wapforum.org/DTD/wml_1.1.xml\">" \
01101 "<wml><card id=\"health\"><p>Ok</p></card></wml>"
01102
01103 static void start_fetch(WAPEvent *event)
01104 {
01105 int ret;
01106 long client_SDU_size;
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;
01116 Octstr *request_body;
01117 int x_wap_tod;
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
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
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;
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
01162
01163
01164
01165 wap_map_url(&url, &send_msisdn_query, &send_msisdn_header,
01166 &send_msisdn_format, &accept_cookies);
01167
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
01187
01188 if (accept_cookies != 0 && (session_id != -1) &&
01189
01190
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
01196
01197
01198
01199
01200
01201
01202
01203
01204
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
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
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
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
01251
01252
01253
01254
01255
01256
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
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
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
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 }
01307
01308
01309
01310 static void dev_null(const char *data, size_t len, void *context)
01311 {
01312
01313 }
01314
01315
01316 static Octstr *convert_wml_to_wmlc(struct content *content)
01317 {
01318 Octstr *wmlc;
01319 int ret;
01320
01321
01322 ret = wml_compile(content->body, content->charset, &wmlc,
01323 content->version);
01324
01325
01326 if (ret == 0)
01327 return wmlc;
01328
01329 octstr_destroy(wmlc);
01330 warning(0, "WSP: WML compilation failed.");
01331 return NULL;
01332 }
01333
01334
01335 static Octstr *convert_wmlscript_to_wmlscriptc(struct content *content)
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(¶ms, 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(¶ms);
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 }
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399 static Octstr *deconvert_multipart_formdata(struct content *content)
01400 {
01401 Octstr *mime;
01402
01403 if ((mime_decompile(content->body, &mime)) == 0)
01404 return mime;
01405
01406 return NULL;
01407 }
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439 static List *negotiate_capabilities(List *req_caps)
01440 {
01441
01442
01443
01444 return gwlist_create();
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462 static void check_application_headers(List **headers,
01463 List **application_headers)
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
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 }
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520 static void decode_bearer_indication(List **headers, List **bearer_headers)
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
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 }
01567
01568
01569
01570
01571
01572
01573 static void split_header_list(List **headers, List **new_headers, char *name)
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 }
01581
01582
01583
01584
01585
01586
01587 static void indicate_push_connection(WAPEvent *e)
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 }
01619
01620
01621 static void indicate_push_disconnect(WAPEvent *e)
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 }
01637
01638
01639
01640
01641
01642 static void confirm_push(WAPEvent *e)
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 }
01655
01656
01657 static void indicate_push_abort(WAPEvent *e)
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 }
01670
01671
01672 static void indicate_push_suspend(WAPEvent *e)
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 }
01682
01683
01684
01685
01686
01687
01688 static void indicate_push_resume(WAPEvent *e)
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 }
01713
01714
01715
01716
01717
01718
01719 static void response_push_connection(WAPEvent *e)
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 }
01733
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.