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 #include <time.h>
00077 #include <ctype.h>
00078
00079 #include "wap_push_ppg.h"
00080 #include "wap/wap_events.h"
00081 #include "wap/wsp_caps.h"
00082 #include "wml_compiler.h"
00083 #include "wap-appl.h"
00084 #include "wap/wsp.h"
00085 #include "wap/wsp_strings.h"
00086 #include "wap_push_si_compiler.h"
00087 #include "wap_push_sl_compiler.h"
00088 #include "wap_push_pap_compiler.h"
00089 #include "wap_push_pap_mime.h"
00090 #include "wap_push_ppg_pushuser.h"
00091
00092 enum {
00093 TIME_EXPIRED = 0,
00094 TIME_TOO_EARLY = 1,
00095 NO_CONSTRAINTS = 2
00096 };
00097
00098
00099
00100
00101 enum {
00102 DEFAULT_HTTP_PORT = 8080,
00103 NO_HTTPS_PORT = -1,
00104 DEFAULT_NUMBER_OF_PUSHES = 100,
00105 PI_TRUSTED = 1,
00106 SSL_CONNECTION_OFF = 0,
00107 DEFAULT_NUMBER_OF_USERS = 1024,
00108 USER_CONFIGURATION_NOT_ADDED = 0
00109 };
00110
00111 enum { USER_CONFIGURATION_ADDED = 1 };
00112
00113 #define DEFAULT_PPG_URL "/wappush"
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 static enum {limbo, running, terminating} run_status = limbo;
00129
00130
00131
00132
00133 static List *ppg_queue = NULL;
00134
00135
00136
00137
00138 static List *pap_queue = NULL;
00139
00140
00141
00142
00143 static List *ppg_machines = NULL;
00144
00145
00146
00147
00148
00149 static List *ppg_unit_pushes = NULL;
00150
00151
00152
00153
00154 static Counter *push_id_counter = NULL;
00155
00156
00157
00158
00159
00160 static Dict *http_clients = NULL;
00161
00162
00163
00164
00165 static Dict *urls = NULL;
00166
00167
00168
00169
00170 struct content {
00171 Octstr *body;
00172 Octstr *type;
00173 Octstr *charset;
00174 };
00175
00176 static wap_dispatch_func_t *dispatch_to_ota;
00177 static wap_dispatch_func_t *dispatch_to_appl;
00178
00179
00180
00181
00182
00183
00184 static Octstr *ppg_url = NULL ;
00185 static long ppg_port = DEFAULT_HTTP_PORT;
00186
00187 #ifdef HAVE_LIBSSL
00188 static long ppg_ssl_port = NO_HTTPS_PORT;
00189 #endif
00190
00191 static long number_of_pushes = DEFAULT_NUMBER_OF_PUSHES;
00192 static int trusted_pi = PI_TRUSTED;
00193 static long number_of_users = DEFAULT_NUMBER_OF_USERS;
00194 static Octstr *ppg_deny_ip = NULL;
00195 static Octstr *ppg_allow_ip = NULL;
00196 static int user_configuration = USER_CONFIGURATION_NOT_ADDED;
00197 static Octstr *global_sender = NULL;
00198 static Octstr *ppg_default_smsc = NULL;
00199 #ifdef HAVE_LIBSSL
00200 static Octstr *ssl_server_cert_file = NULL;
00201 static Octstr *ssl_server_key_file = NULL;
00202 #endif
00203 static Octstr *ppg_dlr_url = NULL;
00204 static Octstr *ppg_smsbox_id = NULL;
00205 static Octstr *service_name = NULL;
00206
00207 struct PAPEvent {
00208 HTTPClient *client;
00209 Octstr *ip;
00210 Octstr *url;
00211 List *push_headers;
00212 Octstr *mime_content;
00213 List *cgivars;
00214 };
00215
00216 typedef struct PAPEvent PAPEvent;
00217
00218
00219
00220
00221
00222
00223
00224
00225 static void ota_read_thread(void *arg);
00226 static void http_read_thread(void *arg);
00227
00228 #ifdef HAVE_LIBSSL
00229 static void https_read_thread(void *arg);
00230 #endif
00231
00232 static void handle_internal_event(WAPEvent *e);
00233 static void pap_request_thread(void *arg);
00234 static int handle_push_message(HTTPClient **c, WAPEvent *ppg_event, int status);
00235 static PAPEvent *pap_event_create(Octstr *ip, Octstr *url, List *push_headers,
00236 Octstr *mime_content, List *cgivars,
00237 HTTPClient *client);
00238 static void pap_event_destroy(PAPEvent *p);
00239 static void pap_event_destroy_item(void *p);
00240 static void pap_event_unpack(PAPEvent *p, Octstr **ip, Octstr **url,
00241 List **push_headers, Octstr **mime_content,
00242 List **cgivars, HTTPClient **client);
00243
00244
00245
00246
00247 static PPGSessionMachine *session_machine_create(WAPAddrTuple *tuple,
00248 WAPEvent *e);
00249 static void session_machine_destroy(void *p);
00250 static PPGPushMachine *push_machine_create(WAPEvent *e,
00251 WAPAddrTuple *tuple);
00252 static void push_machine_destroy(void *pm);
00253 static void push_machines_list_destroy(List *pl);
00254
00255
00256
00257
00258 static void create_session(WAPEvent *e, PPGPushMachine *pm);
00259 static void request_confirmed_push(long last, PPGPushMachine *pm,
00260 PPGSessionMachine *sm);
00261 static void request_unit_push(long last, PPGPushMachine *pm);
00262 static void request_push(long last, PPGPushMachine *sm);
00263 static int response_push_connection(WAPEvent *e, PPGSessionMachine *sm);
00264 static HTTPClient *response_push_message(PPGPushMachine *pm, long code,
00265 int status);
00266
00267
00268
00269
00270
00271 static PPGSessionMachine *session_find_using_pi_client_address(Octstr *addr);
00272 static PPGPushMachine *find_ppg_push_machine_using_pid(PPGSessionMachine *sm,
00273 long pid);
00274 static PPGPushMachine *find_ppg_push_machine_using_pi_push_id(
00275 PPGSessionMachine *sm, Octstr *pi_push_id);
00276 static PPGPushMachine *find_unit_ppg_push_machine_using_pi_push_id(
00277 Octstr *pi_push_id);
00278 static int push_has_pi_push_id(void *a, void *b);
00279 static int push_has_pid(void *a, void *b);
00280 static int session_has_pi_client_address(void *a, void *b);
00281 static int session_has_addr(void *a, void *b);
00282 static int session_has_sid(void *a, void *b);
00283
00284
00285
00286
00287 static int check_capabilities(List *requested, List *assumed);
00288 static int transform_message(WAPEvent **e, WAPAddrTuple **tuple,
00289 List *push_headers, int connected, Octstr **type);
00290 static long check_x_wap_application_id_header(List **push_headers);
00291 static int pap_convert_content(struct content *content);
00292 static int pap_get_content(struct content *content);
00293 static int select_bearer_network(WAPEvent **e);
00294 static int delivery_time_constraints(WAPEvent *e, PPGPushMachine *pm);
00295 static void deliver_confirmed_push(long last, PPGPushMachine *pm,
00296 PPGSessionMachine *sm);
00297 static PPGPushMachine *deliver_unit_push(long last, PPGPushMachine *pm,
00298 PPGSessionMachine *sm, int session_exists);
00299 static int store_push_data(PPGPushMachine **pm, PPGSessionMachine *sm,
00300 WAPEvent *e, WAPAddrTuple *tuple, int cless);
00301 static PPGPushMachine *update_push_data_with_attribute(PPGSessionMachine **sm,
00302 PPGPushMachine *pm, long reason, long status);
00303 static void remove_push_data(PPGSessionMachine *sm, PPGPushMachine *pm,
00304 int cless);
00305 static void remove_session_data(PPGSessionMachine *sm, int status);
00306 static void remove_pushless_session(PPGSessionMachine *sm);
00307 static PPGSessionMachine *store_session_data(PPGSessionMachine *sm,
00308 WAPEvent *e, WAPAddrTuple *tuple, int *session_exists);
00309 static PPGSessionMachine *update_session_data_with_headers(
00310 PPGSessionMachine *sm, PPGPushMachine *pm);
00311 static void deliver_pending_pushes(PPGSessionMachine *sm, int last);
00312 static PPGPushMachine *abort_delivery(PPGSessionMachine *sm, int status);
00313 static PPGSessionMachine *update_session_data(PPGSessionMachine *sm, long sid,
00314 long port, List *caps);
00315 static int confirmation_requested(WAPEvent *e);
00316 static int cless_accepted(WAPEvent *e, PPGSessionMachine *sm);
00317
00318
00319
00320
00321 static int headers_acceptable(List *push_headers, Octstr **content_header);
00322 static int type_is(Octstr *content_header, char *required_type);
00323 static int get_mime_boundary(List *push_headers, Octstr *content_header,
00324 Octstr **boundary);
00325 static void change_header_value(List **push_headers, char *name, char *value);
00326 static void remove_mime_headers(List **push_headers);
00327 static void remove_link_headers(List **push_headers);
00328 static void remove_x_kannel_headers(List **push_headers);
00329
00330
00331
00332
00333 static void send_bad_message_response(HTTPClient **c, Octstr *body_fragment,
00334 int code, int status);
00335 static HTTPClient *send_push_response(WAPEvent *e, int status);
00336 static void send_to_pi(HTTPClient **c, Octstr *reply_body, int status);
00337 static void tell_fatal_error(HTTPClient **c, WAPEvent *e, Octstr *url,
00338 int status, int code);
00339
00340
00341
00342
00343 static int read_ppg_config(Cfg *cfg);
00344 static int ip_allowed_by_ppg(Octstr *ip);
00345
00346
00347
00348
00349 static Octstr *convert_wml_to_wmlc(struct content *content);
00350 static Octstr *convert_si_to_sic(struct content *content);
00351 static Octstr *convert_sl_to_slc(struct content *content);
00352
00353
00354
00355
00356
00357
00358 static Octstr *set_smsc_id(List *headers, Octstr *username, int trusted_pi);
00359 static Octstr *set_dlr_url(List *headers, Octstr *username, int trusted_pi);
00360 static long set_dlr_mask(List *headers, Octstr *dlr_url);
00361 static Octstr *set_smsbox_id(List *headers, Octstr *username, int trusted_pi);
00362 static Octstr *set_service_name(void);
00363
00364
00365
00366
00367 static Octstr *set_time(void);
00368 static int deliver_before_test_cleared(Octstr *before, struct tm now);
00369 static int deliver_after_test_cleared(Octstr *after, struct tm now);
00370 static void session_machine_assert(PPGSessionMachine *sm);
00371 static void push_machine_assert(PPGPushMachine *pm);
00372 static Octstr *tell_ppg_name(void);
00373 static Octstr *describe_code(long code);
00374 static long ota_abort_to_pap(long reason);
00375 static int content_transformable(List *push_headers);
00376 static WAPAddrTuple *set_addr_tuple(Octstr *address, long cliport, long servport,
00377 long address_type, List *push_headers);
00378 static WAPAddrTuple *addr_tuple_change_cliport(WAPAddrTuple *tuple, long port);
00379 static void initialize_time_item_array(long time_data[], struct tm now);
00380 static int date_item_compare(Octstr *before, long time_data, long pos);
00381 static long parse_appid_header(Octstr **assigned_code);
00382 static Octstr *escape_fragment(Octstr *fragment);
00383 static int coriented_deliverable(long code);
00384 static int is_phone_number(long type_of_address);
00385 static void replace_octstr_char(Octstr *os1, Octstr *os2, long *pos);
00386
00387
00388
00389
00390
00391
00392 enum {
00393 TYPE_HTTP = 0,
00394 TYPE_HTTPS = 1
00395 };
00396
00397 void wap_push_ppg_init(wap_dispatch_func_t *ota_dispatch,
00398 wap_dispatch_func_t *appl_dispatch, Cfg *cfg)
00399 {
00400 user_configuration = read_ppg_config(cfg);
00401 if (user_configuration != USER_CONFIGURATION_NOT_ADDED) {
00402 ppg_queue = gwlist_create();
00403 gwlist_add_producer(ppg_queue);
00404 pap_queue = gwlist_create();
00405 gwlist_add_producer(pap_queue);
00406 push_id_counter = counter_create();
00407 ppg_machines = gwlist_create();
00408 ppg_unit_pushes = gwlist_create();
00409
00410 dispatch_to_ota = ota_dispatch;
00411 dispatch_to_appl = appl_dispatch;
00412
00413 http_open_port(ppg_port, TYPE_HTTP);
00414 #ifdef HAVE_LIBSSL
00415 if (ppg_ssl_port != NO_HTTPS_PORT)
00416 http_open_port(ppg_ssl_port, TYPE_HTTPS);
00417 #endif
00418 http_clients = dict_create(number_of_pushes, NULL);
00419 urls = dict_create(number_of_pushes, NULL);
00420
00421 gw_assert(run_status == limbo);
00422 run_status = running;
00423 gwthread_create(ota_read_thread, NULL);
00424 gwthread_create(http_read_thread, NULL);
00425 #ifdef HAVE_LIBSSL
00426 if (ppg_ssl_port != NO_HTTPS_PORT)
00427 gwthread_create(https_read_thread, NULL);
00428 #endif
00429 gwthread_create(pap_request_thread, NULL);
00430 }
00431 }
00432
00433 void wap_push_ppg_shutdown(void)
00434 {
00435 if (user_configuration != USER_CONFIGURATION_NOT_ADDED) {
00436 gw_assert(run_status == running);
00437 run_status = terminating;
00438 gwlist_remove_producer(ppg_queue);
00439 gwlist_remove_producer(pap_queue);
00440 octstr_destroy(ppg_url);
00441 http_close_all_ports();
00442 dict_destroy(http_clients);
00443 dict_destroy(urls);
00444 wap_push_ppg_pushuser_list_destroy();
00445 octstr_destroy(ppg_deny_ip);
00446 octstr_destroy(ppg_allow_ip);
00447 octstr_destroy(global_sender);
00448 octstr_destroy(service_name);
00449 octstr_destroy(ppg_default_smsc);
00450
00451 gwthread_join_every(http_read_thread);
00452 #ifdef HAVE_LIBSSL
00453 if (ppg_ssl_port != NO_HTTPS_PORT)
00454 gwthread_join_every(https_read_thread);
00455 #endif
00456 gwthread_join_every(ota_read_thread);
00457 gwthread_join_every(pap_request_thread);
00458
00459 gwlist_destroy(ppg_queue, wap_event_destroy_item);
00460 gwlist_destroy(pap_queue, pap_event_destroy_item);
00461 counter_destroy(push_id_counter);
00462
00463 debug("wap.push.ppg", 0, "PPG: %ld push session machines left.",
00464 gwlist_len(ppg_machines));
00465 gwlist_destroy(ppg_machines, session_machine_destroy);
00466
00467 debug("wap_push_ppg", 0, "PPG: %ld unit pushes left",
00468 gwlist_len(ppg_unit_pushes));
00469 gwlist_destroy(ppg_unit_pushes, push_machine_destroy);
00470 }
00471 }
00472
00473 void wap_push_ppg_dispatch_event(WAPEvent *e)
00474 {
00475 gw_assert(run_status == running);
00476 gwlist_produce(ppg_queue, e);
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 PPGSessionMachine *wap_push_ppg_have_push_session_for(WAPAddrTuple *tuple)
00486 {
00487 PPGSessionMachine *sm;
00488
00489 gw_assert(tuple);
00490 sm = gwlist_search(ppg_machines, tuple->remote->address, session_has_addr);
00491
00492 return sm;
00493 }
00494
00495
00496
00497
00498
00499
00500 PPGSessionMachine *wap_push_ppg_have_push_session_for_sid(long sid)
00501 {
00502 PPGSessionMachine *sm;
00503
00504 gw_assert(sid >= 0);
00505 sm = gwlist_search(ppg_machines, &sid, session_has_sid);
00506
00507 return sm;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 static int read_ppg_config(Cfg *cfg)
00521 {
00522 CfgGroup *grp;
00523 List *list;
00524
00525 if (cfg == NULL)
00526 return USER_CONFIGURATION_NOT_ADDED;
00527
00528 grp = cfg_get_single_group(cfg, octstr_imm("ppg"));
00529 if ((ppg_url = cfg_get(grp, octstr_imm("ppg-url"))) == NULL)
00530 ppg_url = octstr_imm("/wappush");
00531 cfg_get_integer(&ppg_port, grp, octstr_imm("ppg-port"));
00532 cfg_get_integer(&number_of_pushes, grp, octstr_imm("concurrent-pushes"));
00533 cfg_get_bool(&trusted_pi, grp, octstr_imm("trusted-pi"));
00534 cfg_get_integer(&number_of_users, grp, octstr_imm("users"));
00535 ppg_deny_ip = cfg_get(grp, octstr_imm("ppg-deny-ip"));
00536 ppg_allow_ip = cfg_get(grp, octstr_imm("ppg-allow-ip"));
00537 if ((global_sender = cfg_get(grp, octstr_imm("global-sender"))) == NULL)
00538 global_sender = octstr_format("%s", "1234");
00539 ppg_default_smsc = cfg_get(grp, octstr_imm("default-smsc"));
00540 ppg_dlr_url = cfg_get(grp, octstr_imm("default-dlr-url"));
00541 ppg_smsbox_id = cfg_get(grp, octstr_imm("ppg-smsbox-id"));
00542 if ((service_name = cfg_get(grp, octstr_imm("service-name"))) == NULL)
00543 service_name = octstr_format("%s", "ppg");
00544
00545 #ifdef HAVE_LIBSSL
00546 cfg_get_integer(&ppg_ssl_port, grp, octstr_imm("ppg-ssl-port"));
00547 ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file"));
00548 ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file"));
00549 if (ppg_ssl_port != NO_HTTPS_PORT) {
00550 if (ssl_server_cert_file == NULL || ssl_server_key_file == NULL)
00551 panic(0, "cannot continue without server cert and/or key files");
00552 use_global_server_certkey_file(ssl_server_cert_file, ssl_server_key_file);
00553 }
00554 octstr_destroy(ssl_server_cert_file);
00555 octstr_destroy(ssl_server_key_file);
00556 #endif
00557
00558
00559 if (trusted_pi) {
00560 cfg_destroy(cfg);
00561 return USER_CONFIGURATION_ADDED;
00562 }
00563
00564
00565 if ((list = cfg_get_multi_group(cfg, octstr_imm("wap-push-user")))
00566 == NULL) {
00567 panic(0, "No user group but ppg not trusted, stopping");
00568 gwlist_destroy(list, NULL);
00569 cfg_destroy(cfg);
00570 return USER_CONFIGURATION_NOT_ADDED;
00571 }
00572
00573 if (!wap_push_ppg_pushuser_list_add(list, number_of_pushes,
00574 number_of_users)) {
00575 panic(0, "unable to create users configuration list, exiting");
00576 return USER_CONFIGURATION_NOT_ADDED;
00577 }
00578
00579 cfg_destroy(cfg);
00580 return USER_CONFIGURATION_ADDED;
00581 }
00582
00583 static int ip_allowed_by_ppg(Octstr *ip)
00584 {
00585 if (ip == NULL)
00586 return 0;
00587
00588 if (trusted_pi)
00589 return 1;
00590
00591 if (ppg_deny_ip == NULL && ppg_allow_ip == NULL) {
00592 warning(0, "Your ppg core configuration lacks allowed and denied"
00593 " ip lists");
00594 return 1;
00595 }
00596
00597 if (ppg_deny_ip)
00598 if (octstr_compare(ppg_deny_ip, octstr_imm("*.*.*.*")) == 0) {
00599 panic(0, "Your ppg core configuration deny all ips, exiting");
00600 return 0;
00601 }
00602
00603 if (ppg_allow_ip)
00604 if (octstr_compare(ppg_allow_ip, octstr_imm("*.*.*.*")) == 0) {
00605 warning(0, "Your ppg core configuration allow all ips");
00606 return 1;
00607 }
00608
00609 if (ppg_deny_ip)
00610 if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(ppg_deny_ip, ip,
00611 octstr_imm(";"), octstr_imm("."))) {
00612 error(0, "ip found from denied list");
00613 return 0;
00614 }
00615
00616 if (ppg_allow_ip)
00617 if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(ppg_allow_ip, ip,
00618 octstr_imm(";"), octstr_imm("."))) {
00619 debug("wap.push.ppg.pushuser", 0, "PPG: ip_allowed_by_ppg: ip found"
00620 " from allowed list");
00621 return 1;
00622 }
00623
00624 warning(0, "did not found ip from any of core lists, deny it");
00625 return 0;
00626 }
00627
00628
00629
00630
00631 static void ota_read_thread (void *arg)
00632 {
00633 WAPEvent *e;
00634
00635 while (run_status == running && (e = gwlist_consume(ppg_queue)) != NULL) {
00636 handle_internal_event(e);
00637 }
00638 }
00639
00640
00641
00642
00643 static PAPEvent *pap_event_create(Octstr *ip, Octstr *url, List *push_headers,
00644 Octstr *mime_content, List *cgivars,
00645 HTTPClient *client)
00646 {
00647 PAPEvent *p;
00648
00649 p = gw_malloc(sizeof(PAPEvent));
00650 p->ip = ip;
00651 p->url = url;
00652 p->push_headers = push_headers;
00653 p->mime_content = mime_content;
00654 p->cgivars = cgivars;
00655 p->client = client;
00656
00657 return p;
00658 }
00659
00660 static void pap_event_destroy(PAPEvent *p)
00661 {
00662 if (p == NULL)
00663 return;
00664
00665 gw_free(p);
00666 }
00667
00668 static void pap_event_destroy_item(void *p)
00669 {
00670 pap_event_destroy(p);
00671 }
00672
00673 static void pap_event_unpack(PAPEvent *p, Octstr **ip, Octstr **url,
00674 List **push_headers, Octstr **mime_content,
00675 List **cgivars, HTTPClient **client)
00676 {
00677 *ip = p->ip;
00678 *url = p->url;
00679 *push_headers = p->push_headers;
00680 *mime_content = p->mime_content;
00681 *cgivars = p->cgivars;
00682 *client = p->client;
00683 }
00684
00685 static void http_read_thread(void *arg)
00686 {
00687 PAPEvent *p;
00688 Octstr *ip;
00689 Octstr *url;
00690 List *push_headers;
00691 Octstr *mime_content;
00692 List *cgivars;
00693 HTTPClient *client;
00694
00695 while (run_status == running) {
00696 client = http_accept_request(ppg_port, &ip, &url, &push_headers,
00697 &mime_content, &cgivars);
00698 if (client == NULL)
00699 break;
00700
00701 p = pap_event_create(ip, url, push_headers, mime_content, cgivars,
00702 client);
00703 gwlist_produce(pap_queue, p);
00704 }
00705 }
00706
00707 #ifdef HAVE_LIBSSL
00708 static void https_read_thread(void *arg)
00709 {
00710 PAPEvent *p;
00711 Octstr *ip;
00712 Octstr *url;
00713 List *push_headers;
00714 Octstr *mime_content;
00715 List *cgivars;
00716 HTTPClient *client;
00717
00718 while (run_status == running) {
00719 client = http_accept_request(ppg_ssl_port, &ip, &url, &push_headers,
00720 &mime_content, &cgivars);
00721 if (client == NULL)
00722 break;
00723
00724 p = pap_event_create(ip, url, push_headers, mime_content, cgivars,
00725 client);
00726 gwlist_produce(pap_queue, p);
00727 }
00728 }
00729 #endif
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 static void pap_request_thread(void *arg)
00744 {
00745 WAPEvent *ppg_event;
00746 PAPEvent *p;
00747 size_t push_len;
00748 Octstr *pap_content = NULL;
00749 Octstr *push_data = NULL;
00750 Octstr *rdf_content = NULL;
00751 Octstr *mime_content = NULL;
00752 Octstr *plos = NULL;
00753 Octstr *boundary = NULL;
00754 Octstr *content_header = NULL;
00755 Octstr *url = NULL;
00756 Octstr *ip = NULL;
00757 Octstr *not_found = NULL;
00758 Octstr *username = NULL;
00759 int compiler_status,
00760 http_status;
00761 List *push_headers,
00762 *content_headers,
00763
00764
00765
00766 *cgivars;
00767 HTTPClient *client;
00768 Octstr *dlr_url;
00769
00770 http_status = 0;
00771 url = ip = mime_content = username = NULL;
00772
00773 while (run_status == running && (p = gwlist_consume(pap_queue)) != NULL) {
00774
00775 http_status = HTTP_NOT_FOUND;
00776 pap_event_unpack(p, &ip, &url, &push_headers, &mime_content,
00777 &cgivars, &client);
00778
00779 if (octstr_compare(url, ppg_url) != 0) {
00780 error(0, "Request <%s> from <%s>: service not found",
00781 octstr_get_cstr(url), octstr_get_cstr(ip));
00782 debug("wap.push.ppg", 0, "your configuration uses %s",
00783 octstr_get_cstr(ppg_url));
00784 not_found = octstr_imm("Service not specified\n");
00785 http_send_reply(client, http_status, push_headers, not_found);
00786 goto ferror;
00787 }
00788
00789 http_status = HTTP_UNAUTHORIZED;
00790
00791 if (!ip_allowed_by_ppg(ip)) {
00792 error(0, "Request <%s> from <%s>: ip forbidden, closing the"
00793 " client", octstr_get_cstr(url), octstr_get_cstr(ip));
00794 http_close_client(client);
00795 goto ferror;
00796 }
00797
00798 if (!trusted_pi && user_configuration) {
00799 if (!wap_push_ppg_pushuser_authenticate(client, cgivars, ip,
00800 push_headers, &username)) {
00801 error(0, "Request <%s> from <%s>: authorisation failure",
00802 octstr_get_cstr(url), octstr_get_cstr(ip));
00803 goto ferror;
00804 }
00805 } else {
00806 username = octstr_imm("");
00807 }
00808
00809 http_status = HTTP_ACCEPTED;
00810 info(0, "PPG: Accept request <%s> from <%s>", octstr_get_cstr(url),
00811 octstr_get_cstr(ip));
00812
00813 if (octstr_len(mime_content) == 0) {
00814 warning(0, "PPG: No MIME content received, the request"
00815 " unacceptable");
00816 send_bad_message_response(&client, octstr_imm("No MIME content"),
00817 PAP_BAD_REQUEST, http_status);
00818 if (client == NULL)
00819 break;
00820 goto ferror;
00821 }
00822
00823 if (!push_headers) {
00824 warning(0, "PPG: No push headers received , the request"
00825 " unacceptable");
00826 send_bad_message_response(&client, octstr_imm("No push headers"),
00827 PAP_BAD_REQUEST, http_status);
00828 if (client == NULL)
00829 break;
00830 goto ferror;
00831 }
00832 octstr_destroy(ip);
00833
00834 http_remove_hop_headers(push_headers);
00835 remove_mime_headers(&push_headers);
00836 remove_link_headers(&push_headers);
00837
00838 if (!headers_acceptable(push_headers, &content_header)) {
00839 warning(0, "PPG: Unparsable push headers, the request"
00840 " unacceptable");
00841 send_bad_message_response(&client, content_header, PAP_BAD_REQUEST,
00842 http_status);
00843 if (client == NULL)
00844 break;
00845 goto herror;
00846 }
00847
00848 if (get_mime_boundary(push_headers, content_header, &boundary) == -1) {
00849 warning(0, "PPG: No MIME boundary, the request unacceptable");
00850 send_bad_message_response(&client, content_header, PAP_BAD_REQUEST,
00851 http_status);
00852 if (client == NULL)
00853 break;
00854 goto berror;
00855 }
00856
00857 gw_assert(mime_content);
00858 if (!mime_parse(boundary, mime_content, &pap_content, &push_data,
00859 &content_headers, &rdf_content)) {
00860 send_bad_message_response(&client, mime_content, PAP_BAD_REQUEST,
00861 http_status);
00862 if (client == NULL)
00863 break;
00864 warning(0, "PPG: unable to parse mime content, the request"
00865 " unacceptable");
00866 goto clean;
00867 } else {
00868 debug("wap.push.ppg", 0, "PPG: http_read_thread: pap multipart"
00869 " accepted");
00870 }
00871
00872 push_len = octstr_len(push_data);
00873 http_header_remove_all(push_headers, "Content-Type");
00874 http_append_headers(push_headers, content_headers);
00875 change_header_value(&push_headers, "Content-Length",
00876 octstr_get_cstr(plos = octstr_format("%d", push_len)));
00877 octstr_destroy(plos);
00878 octstr_destroy(content_header);
00879 http_destroy_headers(content_headers);
00880
00881 ppg_event = NULL;
00882 if ((compiler_status = pap_compile(pap_content, &ppg_event)) == -2) {
00883 send_bad_message_response(&client, pap_content, PAP_BAD_REQUEST,
00884 http_status);
00885 if (client == NULL)
00886 break;
00887 warning(0, "PPG: pap control entity erroneous, the request"
00888 " unacceptable");
00889 goto no_compile;
00890 } else if (compiler_status == -1) {
00891 send_bad_message_response(&client, pap_content, PAP_BAD_REQUEST,
00892 http_status);
00893 if (client == NULL)
00894 break;
00895 warning(0, "PPG: non implemented pap feature requested, the"
00896 " request unacceptable");
00897 goto no_compile;
00898 } else {
00899 if (!dict_put_once(http_clients,
00900 ppg_event->u.Push_Message.pi_push_id, client)) {
00901 warning(0, "PPG: duplicate push id, the request unacceptable");
00902 tell_fatal_error(&client, ppg_event, url, http_status,
00903 PAP_DUPLICATE_PUSH_ID);
00904 if (client == NULL)
00905 break;
00906 goto not_acceptable;
00907 }
00908
00909 dict_put(urls, ppg_event->u.Push_Message.pi_push_id, url);
00910
00911 if (is_phone_number(ppg_event->u.Push_Message.address_type)) {
00912 if (!trusted_pi && user_configuration &&
00913 !wap_push_ppg_pushuser_client_phone_number_acceptable(
00914 username, ppg_event->u.Push_Message.address_value)) {
00915 tell_fatal_error(&client, ppg_event, url, http_status,
00916 PAP_FORBIDDEN);
00917 if (client == NULL)
00918 break;
00919 goto not_acceptable;
00920 }
00921 }
00922
00923 debug("wap.push.ppg", 0, "PPG: http_read_thread: pap control"
00924 " entity compiled ok");
00925 ppg_event->u.Push_Message.push_data = octstr_duplicate(push_data);
00926 ppg_event->u.Push_Message.smsc_id = set_smsc_id(push_headers, username,
00927 trusted_pi);
00928 dlr_url = set_dlr_url(push_headers, username, trusted_pi);
00929 ppg_event->u.Push_Message.dlr_url = dlr_url;
00930 ppg_event->u.Push_Message.dlr_mask = set_dlr_mask(push_headers, dlr_url);
00931 ppg_event->u.Push_Message.smsbox_id = set_smsbox_id(push_headers, username,
00932 trusted_pi);
00933 ppg_event->u.Push_Message.service_name = set_service_name();
00934 remove_x_kannel_headers(&push_headers);
00935 ppg_event->u.Push_Message.push_headers = http_header_duplicate(push_headers);
00936
00937 if (!handle_push_message(&client, ppg_event, http_status)) {
00938 if (client == NULL)
00939 break;
00940 goto no_transform;
00941 }
00942 }
00943
00944 pap_event_destroy(p);
00945 http_destroy_headers(push_headers);
00946 http_destroy_cgiargs(cgivars);
00947 octstr_destroy(username);
00948 octstr_destroy(mime_content);
00949 octstr_destroy(pap_content);
00950 octstr_destroy(push_data);
00951 octstr_destroy(rdf_content);
00952 octstr_destroy(boundary);
00953 continue;
00954
00955 no_transform:
00956 pap_event_destroy(p);
00957 http_destroy_headers(push_headers);
00958 http_destroy_cgiargs(cgivars);
00959 octstr_destroy(username);
00960 octstr_destroy(mime_content);
00961 octstr_destroy(pap_content);
00962 octstr_destroy(push_data);
00963 octstr_destroy(rdf_content);
00964 octstr_destroy(boundary);
00965 continue;
00966
00967 no_compile:
00968 pap_event_destroy(p);
00969 http_destroy_headers(push_headers);
00970 http_destroy_cgiargs(cgivars);
00971 octstr_destroy(username);
00972 octstr_destroy(mime_content);
00973 octstr_destroy(push_data);
00974 octstr_destroy(rdf_content);
00975 octstr_destroy(boundary);
00976 octstr_destroy(url);
00977 continue;
00978
00979 not_acceptable:
00980 pap_event_destroy(p);
00981 http_destroy_headers(push_headers);
00982 http_destroy_cgiargs(cgivars);
00983 octstr_destroy(username);
00984 octstr_destroy(mime_content);
00985 octstr_destroy(pap_content);
00986 octstr_destroy(push_data);
00987 octstr_destroy(rdf_content);
00988 octstr_destroy(boundary);
00989 octstr_destroy(url);
00990 continue;
00991
00992 clean:
00993 pap_event_destroy(p);
00994 http_destroy_headers(push_headers);
00995 http_destroy_headers(content_headers);
00996 octstr_destroy(pap_content);
00997 octstr_destroy(push_data);
00998 octstr_destroy(rdf_content);
00999 octstr_destroy(content_header);
01000 octstr_destroy(boundary);
01001 octstr_destroy(url);
01002 continue;
01003
01004 ferror:
01005 pap_event_destroy(p);
01006 http_destroy_headers(push_headers);
01007 http_destroy_cgiargs(cgivars);
01008 octstr_destroy(username);
01009 octstr_destroy(url);
01010 octstr_destroy(ip);
01011 octstr_destroy(mime_content);
01012 continue;
01013
01014 herror:
01015 pap_event_destroy(p);
01016 http_destroy_headers(push_headers);
01017 http_destroy_cgiargs(cgivars);
01018 octstr_destroy(username);
01019 octstr_destroy(url);
01020 continue;
01021
01022 berror:
01023 pap_event_destroy(p);
01024 http_destroy_headers(push_headers);
01025 http_destroy_cgiargs(cgivars);
01026 octstr_destroy(username);
01027 octstr_destroy(mime_content);
01028 octstr_destroy(content_header);
01029 octstr_destroy(boundary);
01030 octstr_destroy(url);
01031 continue;
01032 }
01033 }
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 static int handle_push_message(HTTPClient **c, WAPEvent *e, int status)
01044 {
01045 int cless,
01046 session_exists,
01047 bearer_supported,
01048 dummy,
01049 constraints,
01050 message_transformable,
01051 coriented_possible;
01052
01053 long coded_appid_value;
01054
01055 PPGPushMachine *pm;
01056 PPGSessionMachine *sm;
01057 WAPAddrTuple *tuple=NULL;
01058 Octstr *push_data=NULL;
01059 Octstr *cliaddr=NULL;
01060 Octstr *type=NULL;
01061
01062 List *push_headers;
01063
01064 push_data = e->u.Push_Message.push_data;
01065 push_headers = e->u.Push_Message.push_headers;
01066 cliaddr = e->u.Push_Message.address_value;
01067 session_exists = 0;
01068
01069 sm = session_find_using_pi_client_address(cliaddr);
01070 coded_appid_value = check_x_wap_application_id_header(&push_headers);
01071 cless = cless_accepted(e, sm);
01072 message_transformable = transform_message(&e, &tuple, push_headers, cless,
01073 &type);
01074
01075 if (!sm && !cless) {
01076 sm = store_session_data(sm, e, tuple, &session_exists);
01077 }
01078
01079 if (!store_push_data(&pm, sm, e, tuple, cless)) {
01080 warning(0, "PPG: handle_push_message: duplicate push id");
01081 *c = response_push_message(pm, PAP_DUPLICATE_PUSH_ID, status);
01082 goto no_start;
01083 }
01084
01085 if (!message_transformable) {
01086 pm = update_push_data_with_attribute(&sm, pm,
01087 PAP_TRANSFORMATION_FAILURE, PAP_UNDELIVERABLE1);
01088 if (tuple != NULL)
01089 *c = response_push_message(pm, PAP_TRANSFORMATION_FAILURE, status);
01090 else
01091 *c = response_push_message(pm, PAP_ADDRESS_ERROR, status);
01092 goto no_transformation;
01093 }
01094
01095 dummy = 0;
01096 pm = update_push_data_with_attribute(&sm, pm, dummy, PAP_PENDING);
01097
01098 bearer_supported = select_bearer_network(&e);
01099 if (!bearer_supported) {
01100 pm = update_push_data_with_attribute(&sm, pm, dummy,
01101 PAP_UNDELIVERABLE2);
01102 *c = response_push_message(pm, PAP_REQUIRED_BEARER_NOT_AVAILABLE, status);
01103 goto no_start;
01104 }
01105
01106 if ((constraints = delivery_time_constraints(e, pm)) == TIME_EXPIRED) {
01107 pm = update_push_data_with_attribute(&sm, pm, PAP_FORBIDDEN,
01108 PAP_EXPIRED);
01109 *c = response_push_message(pm, PAP_FORBIDDEN, status);
01110 goto no_start;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119 *c = response_push_message(pm, PAP_ACCEPTED_FOR_PROCESSING, status);
01120 info(0, "PPG: handle_push_message: push message accepted for processing");
01121
01122 if (constraints == TIME_TOO_EARLY)
01123 goto store_push;
01124
01125 if (constraints == NO_CONSTRAINTS) {
01126 http_header_mark_transformation(pm->push_headers, pm->push_data, type);
01127 if (sm)
01128 sm = update_session_data_with_headers(sm, pm);
01129
01130 if (!confirmation_requested(e)) {
01131 pm = deliver_unit_push(NOT_LAST, pm, sm, session_exists);
01132 goto unit_push_delivered;
01133 }
01134
01135 if (session_exists) {
01136 deliver_confirmed_push(NOT_LAST, pm, sm);
01137 } else {
01138 coriented_possible = coriented_deliverable(coded_appid_value);
01139 http_header_remove_all(e->u.Push_Message.push_headers,
01140 "Content-Type");
01141 if (coriented_possible) {
01142 create_session(e, pm);
01143 } else {
01144 warning(0, "PPG: handle_push_message: wrong app id for confirmed"
01145 " push session creation");
01146 *c = response_push_message(pm, PAP_BAD_REQUEST, status);
01147 }
01148 }
01149 }
01150
01151 wap_addr_tuple_destroy(tuple);
01152 octstr_destroy(type);
01153 wap_event_destroy(e);
01154 return 1;
01155
01156 unit_push_delivered:
01157 wap_addr_tuple_destroy(tuple);
01158 remove_push_data(sm, pm, cless);
01159 octstr_destroy(type);
01160 wap_event_destroy(e);
01161 return 1;
01162
01163 store_push:
01164 wap_addr_tuple_destroy(tuple);
01165 octstr_destroy(type);
01166 wap_event_destroy(e);
01167 return 1;
01168
01169 no_transformation:
01170 wap_addr_tuple_destroy(tuple);
01171 remove_push_data(sm, pm, cless);
01172 if (sm)
01173 remove_pushless_session(sm);
01174 wap_event_destroy(e);
01175 return 0;
01176
01177 no_start:
01178 wap_addr_tuple_destroy(tuple);
01179 octstr_destroy(type);
01180 remove_push_data(sm, pm, cless);
01181 if (sm)
01182 remove_pushless_session(sm);
01183 wap_event_destroy(e);
01184 return 1;
01185 }
01186
01187
01188
01189
01190 static void handle_internal_event(WAPEvent *e)
01191 {
01192 long sid,
01193 pid,
01194 reason,
01195 port;
01196 int http_status;
01197 PPGPushMachine *pm;
01198 PPGSessionMachine *sm;
01199 WAPAddrTuple *tuple;
01200 List *caps;
01201
01202 http_status = HTTP_OK;
01203 switch (e->type) {
01204
01205
01206
01207
01208
01209
01210 case Pom_Connect_Ind:
01211 debug("wap.push.ppg", 0, "PPG: handle_internal_event: connect"
01212 " indication from OTA");
01213 sid = e->u.Pom_Connect_Ind.session_id;
01214 tuple = e->u.Pom_Connect_Ind.addr_tuple;
01215 port = tuple->remote->port;
01216 caps = e->u.Pom_Connect_Ind.requested_capabilities;
01217
01218 sm = wap_push_ppg_have_push_session_for(tuple);
01219 sm = update_session_data(sm, sid, port, caps);
01220
01221 if (!response_push_connection(e, sm)) {
01222 pm = abort_delivery(sm, http_status);
01223 wap_event_destroy(e);
01224 return;
01225 }
01226
01227
01228
01229
01230 deliver_pending_pushes(sm, NOT_LAST);
01231 wap_event_destroy(e);
01232 break;
01233
01234 case Pom_Disconnect_Ind:
01235 debug("wap.push.ppg", 0, "PPG: handle_internal_event: disconnect"
01236 " indication from OTA");
01237 sm = wap_push_ppg_have_push_session_for_sid(
01238 e->u.Pom_Disconnect_Ind.session_handle);
01239 remove_session_data(sm, http_status);
01240 wap_event_destroy(e);
01241 break;
01242
01243
01244
01245
01246
01247
01248
01249 case Po_ConfirmedPush_Cnf:
01250 debug("wap.push.ppg", 0, "PPG: handle_internal_event: push"
01251 " confirmation from OTA");
01252 sid = e->u.Po_ConfirmedPush_Cnf.session_handle;
01253 pid = e->u.Po_ConfirmedPush_Cnf.server_push_id;
01254
01255 sm = wap_push_ppg_have_push_session_for_sid(sid);
01256 pm = find_ppg_push_machine_using_pid(sm, pid);
01257 pm = update_push_data_with_attribute(&sm, pm, PAP_CONFIRMED,
01258 PAP_DELIVERED2);
01259 wap_event_destroy(e);
01260 remove_push_data(sm, pm, 0);
01261 break;
01262
01263
01264
01265
01266 case Po_PushAbort_Ind:
01267 debug("wap.push.ppg", 0, "PPG: handle_internal_event: abort"
01268 " indication from OTA");
01269 sid = e->u.Po_PushAbort_Ind.session_handle;
01270 pid = e->u.Po_PushAbort_Ind.push_id;
01271
01272 sm = wap_push_ppg_have_push_session_for_sid(sid);
01273 pm = find_ppg_push_machine_using_pid(sm, pid);
01274 session_machine_assert(sm);
01275 push_machine_assert(pm);
01276 reason = e->u.Po_PushAbort_Ind.reason;
01277 pm = update_push_data_with_attribute(&sm, pm, reason, PAP_ABORTED);
01278 remove_session_data(sm, http_status);
01279 wap_event_destroy(e);
01280 break;
01281
01282
01283
01284
01285 default:
01286 debug("wap.ppg", 0, "PPG: handle_internal_event: an unhandled event");
01287 wap_event_dump(e);
01288 wap_event_destroy(e);
01289 break;
01290 }
01291 }
01292
01293
01294
01295
01296
01297
01298 static PPGSessionMachine *session_machine_create(WAPAddrTuple *tuple,
01299 WAPEvent *e)
01300 {
01301 PPGSessionMachine *m;
01302
01303 gw_assert(e->type = Push_Message);
01304
01305 m = gw_malloc(sizeof(PPGSessionMachine));
01306
01307 #define INTEGER(name) m->name = 0;
01308 #define OCTSTR(name) m->name = NULL;
01309 #define ADDRTUPLE(name) m->name = NULL;
01310 #define PUSHMACHINES(name) m->name = gwlist_create();
01311 #define CAPABILITIES(name) m->name = NULL;
01312 #define MACHINE(fields) fields
01313 #include "wap_ppg_session_machine.def"
01314
01315 m->pi_client_address = octstr_duplicate(e->u.Push_Message.address_value);
01316 m->addr_tuple = wap_addr_tuple_duplicate(tuple);
01317 m->assumed_capabilities =
01318 wsp_cap_duplicate_list(e->u.Push_Message.pi_capabilities);
01319 m->preferconfirmed_value = PAP_CONFIRMED;
01320
01321 gwlist_append(ppg_machines, m);
01322 debug("wap.push.ppg", 0, "PPG: Created PPGSessionMachine %ld",
01323 m->session_id);
01324
01325 return m;
01326 }
01327
01328 static void session_machine_destroy(void *p)
01329 {
01330 PPGSessionMachine *sm;
01331
01332 if (p == NULL)
01333 return;
01334
01335 sm = p;
01336 debug("wap.push.ppg", 0, "PPG: destroying PPGSEssionMachine %ld",
01337 sm->session_id);
01338
01339 #define OCTSTR(name) octstr_destroy(sm->name);
01340 #define ADDRTUPLE(name) wap_addr_tuple_destroy(sm->name);
01341 #define INTEGER(name) sm->name = 0;
01342 #define PUSHMACHINES(name) push_machines_list_destroy(sm->name);
01343 #define CAPABILITIES(name) wsp_cap_destroy_list(sm->name);
01344 #define MACHINE(fields) fields
01345 #include "wap_ppg_session_machine.def"
01346 gw_free(sm);
01347 }
01348
01349
01350
01351
01352
01353 static PPGPushMachine *push_machine_create(WAPEvent *e, WAPAddrTuple *tuple)
01354 {
01355 PPGPushMachine *m;
01356
01357 m = gw_malloc(sizeof(PPGPushMachine));
01358
01359 #define INTEGER(name) m->name = 0;
01360 #define OCTSTR(name) m->name = NULL;
01361 #define OPTIONAL_OCTSTR(name) m->name = NULL;
01362 #define ADDRTUPLE(name) m->name = NULL;
01363 #define CAPABILITIES m->name = NULL;
01364 #define HTTPHEADER(name) m->name = NULL;
01365 #define MACHINE(fields) fields
01366 #include "wap_ppg_push_machine.def"
01367
01368 m->addr_tuple = wap_addr_tuple_duplicate(tuple);
01369 m->pi_push_id = octstr_duplicate(e->u.Push_Message.pi_push_id);
01370 m->push_id = counter_increase(push_id_counter);
01371 m->delivery_method = e->u.Push_Message.delivery_method;
01372 m->deliver_after_timestamp =
01373 octstr_duplicate(e->u.Push_Message.deliver_after_timestamp);
01374 m->priority = e->u.Push_Message.priority;
01375 m->push_headers = http_header_duplicate(e->u.Push_Message.push_headers);
01376 m->push_data = octstr_duplicate(e->u.Push_Message.push_data);
01377
01378 m->address_type = e->u.Push_Message.address_type;
01379 if (e->u.Push_Message.smsc_id != NULL)
01380 m->smsc_id = octstr_duplicate(e->u.Push_Message.smsc_id);
01381 else
01382 m->smsc_id = NULL;
01383 if (e->u.Push_Message.dlr_url != NULL)
01384 m->dlr_url = octstr_duplicate(e->u.Push_Message.dlr_url);
01385 else
01386 m->dlr_url = NULL;
01387 m->dlr_mask = e->u.Push_Message.dlr_mask;
01388 if (e->u.Push_Message.smsbox_id != NULL)
01389 m->smsbox_id = octstr_duplicate(e->u.Push_Message.smsbox_id);
01390 else
01391 m->smsbox_id = NULL;
01392 m->service_name = octstr_duplicate(e->u.Push_Message.service_name);
01393
01394 m->progress_notes_requested = e->u.Push_Message.progress_notes_requested;
01395 if (e->u.Push_Message.progress_notes_requested)
01396 m->ppg_notify_requested_to =
01397 octstr_duplicate(e->u.Push_Message.ppg_notify_requested_to);
01398
01399 debug("wap.push.ppg", 0, "PPG: push machine %ld created", m->push_id);
01400
01401 return m;
01402 }
01403
01404
01405
01406
01407
01408 static void push_machine_destroy(void *p)
01409 {
01410 PPGPushMachine *pm;
01411
01412 if (p == NULL)
01413 return;
01414
01415 pm = p;
01416
01417 debug("wap.push.ppg", 0, "PPG: destroying push machine %ld",
01418 pm->push_id);
01419 #define OCTSTR(name) octstr_destroy(pm->name);
01420 #define OPTIONAL_OCTSTR(name) octstr_destroy(pm->name);
01421 #define INTEGER(name)
01422 #define ADDRTUPLE(name) wap_addr_tuple_destroy(pm->name);
01423 #define CAPABILITIES(name) wap_cap_destroy_list(pm->name);
01424 #define HTTPHEADER(name) http_destroy_headers(pm->name);
01425 #define MACHINE(fields) fields
01426 #include "wap_ppg_push_machine.def"
01427
01428 gw_free(p);
01429 }
01430
01431 static void push_machines_list_destroy(List *machines)
01432 {
01433 if (machines == NULL)
01434 return;
01435
01436 gwlist_destroy(machines, push_machine_destroy);
01437 }
01438
01439 static int session_has_addr(void *a, void *b)
01440 {
01441 Octstr *cliaddr;
01442 PPGSessionMachine *sm;
01443
01444 cliaddr = b;
01445 sm = a;
01446
01447 return octstr_compare(sm->addr_tuple->remote->address, cliaddr) == 0;
01448 }
01449
01450 static int session_has_sid(void *a, void *b)
01451 {
01452 PPGSessionMachine *sm;
01453 long *sid;
01454
01455 sid = b;
01456 sm = a;
01457
01458 return *sid == sm->session_id;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467 static void create_session(WAPEvent *e, PPGPushMachine *pm)
01468 {
01469 WAPEvent *ota_event;
01470 List *push_headers;
01471 Octstr *smsc_id;
01472 Octstr *dlr_url;
01473 Octstr *smsbox_id;
01474 Octstr *service_name;
01475
01476 gw_assert(e->type == Push_Message);
01477 push_machine_assert(pm);
01478
01479 push_headers = http_header_duplicate(e->u.Push_Message.push_headers);
01480 smsc_id = octstr_duplicate(e->u.Push_Message.smsc_id);
01481 dlr_url = octstr_duplicate(e->u.Push_Message.dlr_url);
01482 smsbox_id = octstr_duplicate(e->u.Push_Message.smsbox_id);
01483 service_name = octstr_duplicate(e->u.Push_Message.service_name);
01484
01485 ota_event = wap_event_create(Pom_SessionRequest_Req);
01486 ota_event->u.Pom_SessionRequest_Req.addr_tuple =
01487 addr_tuple_change_cliport(pm->addr_tuple,
01488 CONNECTIONLESS_PUSH_CLIPORT);
01489 ota_event->u.Pom_SessionRequest_Req.push_headers = push_headers;
01490 ota_event->u.Pom_SessionRequest_Req.push_id = pm->push_id;
01491 ota_event->u.Pom_SessionRequest_Req.address_type = pm->address_type;
01492 if (smsc_id != NULL)
01493 ota_event->u.Pom_SessionRequest_Req.smsc_id = smsc_id;
01494 else
01495 ota_event->u.Pom_SessionRequest_Req.smsc_id = NULL;
01496 if (dlr_url != NULL)
01497 ota_event->u.Pom_SessionRequest_Req.dlr_url = dlr_url;
01498 else
01499 ota_event->u.Pom_SessionRequest_Req.dlr_url = NULL;
01500 ota_event->u.Pom_SessionRequest_Req.dlr_mask = e->u.Push_Message.dlr_mask;
01501 if (smsbox_id != NULL)
01502 ota_event->u.Pom_SessionRequest_Req.smsbox_id = smsbox_id;
01503 else
01504 ota_event->u.Pom_SessionRequest_Req.smsbox_id = NULL;
01505 ota_event->u.Pom_SessionRequest_Req.service_name = service_name;
01506
01507 dispatch_to_ota(ota_event);
01508 }
01509
01510
01511
01512
01513
01514 static void request_confirmed_push(long last, PPGPushMachine *pm,
01515 PPGSessionMachine *sm)
01516 {
01517 WAPEvent *ota_event;
01518 List *push_headers;
01519
01520 gw_assert(last == 0 || last == 1);
01521 push_machine_assert(pm);
01522 session_machine_assert(sm);
01523
01524 push_headers = http_header_duplicate(pm->push_headers);
01525
01526 ota_event = wap_event_create(Po_ConfirmedPush_Req);
01527 ota_event->u.Po_ConfirmedPush_Req.server_push_id = pm->push_id;
01528 ota_event->u.Po_ConfirmedPush_Req.push_headers = push_headers;
01529 ota_event->u.Po_ConfirmedPush_Req.authenticated = pm->authenticated;
01530 ota_event->u.Po_ConfirmedPush_Req.trusted = pm->trusted;
01531 ota_event->u.Po_ConfirmedPush_Req.last = last;
01532
01533 if (pm->push_data != NULL)
01534 ota_event->u.Po_ConfirmedPush_Req.push_body =
01535 octstr_duplicate(pm->push_data);
01536 else
01537 ota_event->u.Po_ConfirmedPush_Req.push_body = NULL;
01538
01539 ota_event->u.Po_ConfirmedPush_Req.session_handle = sm->session_id;
01540 debug("wap.push.ota", 0, "PPG: confirmed push request to OTA");
01541
01542 dispatch_to_ota(ota_event);
01543 }
01544
01545
01546
01547
01548
01549 static void request_unit_push(long last, PPGPushMachine *pm)
01550 {
01551 WAPEvent *ota_event;
01552 List *push_headers;
01553
01554 gw_assert(last == 0 || last == 1);
01555 push_machine_assert(pm);
01556
01557 push_headers = http_header_duplicate(pm->push_headers);
01558
01559 ota_event = wap_event_create(Po_Unit_Push_Req);
01560 ota_event->u.Po_Unit_Push_Req.addr_tuple =
01561 wap_addr_tuple_duplicate(pm->addr_tuple);
01562 ota_event->u.Po_Unit_Push_Req.push_id = pm->push_id;
01563 ota_event->u.Po_Unit_Push_Req.push_headers = push_headers;
01564 ota_event->u.Po_Unit_Push_Req.authenticated = pm->authenticated;
01565 ota_event->u.Po_Unit_Push_Req.trusted = pm->trusted;
01566 ota_event->u.Po_Unit_Push_Req.last = last;
01567
01568 ota_event->u.Po_Unit_Push_Req.address_type = pm->address_type;
01569 if (pm->smsc_id != NULL)
01570 ota_event->u.Po_Unit_Push_Req.smsc_id = octstr_duplicate(pm->smsc_id);
01571 else
01572 ota_event->u.Po_Unit_Push_Req.smsc_id = NULL;
01573 if (pm->dlr_url != NULL)
01574 ota_event->u.Po_Unit_Push_Req.dlr_url = octstr_duplicate(pm->dlr_url);
01575 else
01576 ota_event->u.Po_Unit_Push_Req.dlr_url = NULL;
01577 ota_event->u.Po_Unit_Push_Req.dlr_mask = pm->dlr_mask;
01578 if (pm->smsbox_id != NULL)
01579 ota_event->u.Po_Unit_Push_Req.smsbox_id = octstr_duplicate(pm->smsbox_id);
01580 else
01581 ota_event->u.Po_Unit_Push_Req.smsbox_id = NULL;
01582 if (pm->service_name != NULL)
01583 ota_event->u.Po_Unit_Push_Req.service_name = octstr_duplicate(pm->service_name);
01584
01585 ota_event->u.Po_Unit_Push_Req.push_body = octstr_duplicate(pm->push_data);
01586
01587 dispatch_to_ota(ota_event);
01588 debug("wap.push.ppg", 0, "PPG: OTA request for unit push");
01589 }
01590
01591 static void request_push(long last, PPGPushMachine *pm)
01592 {
01593 WAPEvent *ota_event;
01594 List *push_headers;
01595
01596 gw_assert(last == 0 || last == 1);
01597 push_machine_assert(pm);
01598
01599 push_headers = http_header_duplicate(pm->push_headers);
01600
01601 ota_event = wap_event_create(Po_Push_Req);
01602 ota_event->u.Po_Push_Req.push_headers = push_headers;
01603 ota_event->u.Po_Push_Req.authenticated = pm->authenticated;
01604 ota_event->u.Po_Push_Req.trusted = pm->trusted;
01605 ota_event->u.Po_Push_Req.last = last;
01606
01607 if (pm->push_data != NULL)
01608 ota_event->u.Po_Push_Req.push_body =
01609 octstr_duplicate(pm->push_data);
01610 else
01611 ota_event->u.Po_Push_Req.push_body = NULL;
01612
01613 ota_event->u.Po_Push_Req.session_handle = pm->session_id;
01614 debug("wap.push.ppg", 0, "PPG: OTA request for push");
01615
01616 dispatch_to_ota(ota_event);
01617 }
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636 static int response_push_connection(WAPEvent *e, PPGSessionMachine *sm)
01637 {
01638 WAPEvent *appl_event;
01639
01640 gw_assert(e->type == Pom_Connect_Ind);
01641
01642 if (sm->assumed_capabilities != NULL && check_capabilities(
01643 e->u.Pom_Connect_Ind.requested_capabilities,
01644 sm->assumed_capabilities) == 0)
01645 return 0;
01646
01647 appl_event = wap_event_create(Pom_Connect_Res);
01648 appl_event->u.Pom_Connect_Res.negotiated_capabilities =
01649 wsp_cap_duplicate_list(e->u.Pom_Connect_Ind.requested_capabilities);
01650 appl_event->u.Pom_Connect_Res.session_id = e->u.Pom_Connect_Ind.session_id;
01651
01652 dispatch_to_appl(appl_event);
01653
01654 return 1;
01655 }
01656
01657
01658
01659
01660
01661
01662 static HTTPClient *response_push_message(PPGPushMachine *pm, long code, int status)
01663 {
01664 WAPEvent *e;
01665 HTTPClient *c;
01666
01667 push_machine_assert(pm);
01668
01669 e = wap_event_create(Push_Response);
01670 e->u.Push_Response.pi_push_id = octstr_duplicate(pm->pi_push_id);
01671 e->u.Push_Response.sender_name = tell_ppg_name();
01672 e->u.Push_Response.reply_time = set_time();
01673 e->u.Push_Response.code = code;
01674 e->u.Push_Response.desc = describe_code(code);
01675
01676 c = send_push_response(e, status);
01677
01678 return c;
01679 }
01680
01681
01682 static int check_capabilities(List *requested, List *assumed)
01683 {
01684 int is_capable;
01685
01686 is_capable = 1;
01687
01688 return is_capable;
01689 }
01690
01691
01692
01693
01694
01695
01696 static Octstr *set_time(void)
01697 {
01698 Octstr *current_time;
01699 struct tm now;
01700
01701 now = gw_gmtime(time(NULL));
01702 current_time = octstr_format("%04d-%02d-%02dT%02d:%02d:%02dZ",
01703 now.tm_year + 1900, now.tm_mon + 1,
01704 now.tm_mday, now.tm_hour, now.tm_min,
01705 now.tm_sec);
01706
01707 return current_time;
01708 }
01709
01710 static void session_machine_assert(PPGSessionMachine *sm)
01711 {
01712 gw_assert(sm);
01713 gw_assert(sm->session_id >= 0);
01714 gw_assert(sm->addr_tuple);
01715 gw_assert(sm->pi_client_address);
01716 }
01717
01718 static void push_machine_assert(PPGPushMachine *pm)
01719 {
01720 gw_assert(pm);
01721 gw_assert(pm->pi_push_id);
01722 gw_assert(pm->push_id >= 0);
01723 gw_assert(pm->session_id >= 0);
01724 gw_assert(pm->addr_tuple);
01725 gw_assert(pm->trusted == 1 || pm->trusted == 0);
01726 gw_assert(pm->authenticated == 1 || pm->authenticated == 0);
01727 }
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752 static int transform_message(WAPEvent **e, WAPAddrTuple **tuple,
01753 List *push_headers, int cless_accepted, Octstr **type)
01754 {
01755 int message_deliverable;
01756 struct content content;
01757 Octstr *cliaddr;
01758 long cliport,
01759 servport,
01760 address_type;
01761
01762 gw_assert((**e).type == Push_Message);
01763 if ((**e).u.Push_Message.push_headers == NULL)
01764 goto herror;
01765
01766 cliaddr = (**e).u.Push_Message.address_value;
01767 push_headers = (**e).u.Push_Message.push_headers;
01768
01769 if (!cless_accepted) {
01770 cliport = CONNECTED_CLIPORT;
01771 servport = CONNECTED_SERVPORT;
01772 } else {
01773 cliport = CONNECTIONLESS_PUSH_CLIPORT;
01774 servport = CONNECTIONLESS_SERVPORT;
01775 }
01776
01777 address_type = (**e).u.Push_Message.address_type;
01778 *tuple = set_addr_tuple(cliaddr, cliport, servport, address_type, push_headers);
01779
01780 if (!content_transformable(push_headers))
01781 goto no_transform;
01782
01783 content.charset = NULL;
01784 content.type = NULL;
01785
01786 content.body = (**e).u.Push_Message.push_data;
01787 if (content.body == NULL)
01788 goto no_transform;
01789
01790 content.type = http_header_find_first(push_headers, "Content-Transfer-Encoding");
01791 if (content.type) {
01792 octstr_strip_blanks(content.type);
01793 debug("wap.push.ppg", 0, "PPG: Content-Transfer-Encoding is \"%s\"",
01794 octstr_get_cstr (content.type));
01795 message_deliverable = pap_get_content(&content);
01796
01797 if (message_deliverable) {
01798 change_header_value(&push_headers, "Content-Transfer-Encoding",
01799 "binary");
01800 } else {
01801 goto error;
01802 }
01803 }
01804
01805 octstr_destroy(content.type);
01806 http_header_get_content_type(push_headers, &content.type, &content.charset);
01807 message_deliverable = pap_convert_content(&content);
01808
01809 if (content.type == NULL)
01810 goto error;
01811
01812 if (message_deliverable) {
01813 *type = content.type;
01814 } else {
01815 goto error;
01816 }
01817
01818 (**e).u.Push_Message.push_data = content.body;
01819 octstr_destroy(content.charset);
01820
01821 debug("wap.push.ppg", 0, "PPG: transform_message: push message content"
01822 " and headers valid");
01823 return 1;
01824
01825 herror:
01826 warning(0, "PPG: transform_message: no push headers, cannot accept");
01827 octstr_destroy(content.type);
01828 return 0;
01829
01830 error:
01831 warning(0, "PPG: transform_message: push content erroneous, cannot"
01832 " accept");
01833 octstr_destroy(content.type);
01834 octstr_destroy(content.charset);
01835 return 0;
01836
01837 no_transform:
01838 warning(0, "PPG: transform_message: push content non transformable");
01839 return 1;
01840 }
01841
01842
01843
01844
01845
01846
01847
01848
01849 static long check_x_wap_application_id_header(List **push_headers)
01850 {
01851 Octstr *appid_content;
01852 long coded_value;
01853 Octstr *cos;
01854
01855 if (*push_headers == NULL)
01856 return -2;
01857
01858 appid_content = http_header_find_first(*push_headers,
01859 "X-WAP-Application-Id");
01860
01861 if (appid_content == NULL) {
01862 octstr_destroy(appid_content);
01863 return -1;
01864 }
01865
01866 if ((coded_value = parse_appid_header(&appid_content)) < 0) {
01867 octstr_destroy(appid_content);
01868 return -2;
01869 }
01870
01871 if (coded_value == 2) {
01872 octstr_destroy(appid_content);
01873 http_header_remove_all(*push_headers, "X-WAP-Application-Id");
01874 return -1;
01875 }
01876
01877 cos = octstr_format("%ld", coded_value);
01878 http_header_remove_all(*push_headers, "X-WAP-Application-Id");
01879 http_header_add(*push_headers, "X-WAP-Application-Id", octstr_get_cstr(cos));
01880
01881 octstr_destroy(appid_content);
01882 octstr_destroy(cos);
01883
01884 return coded_value;
01885 }
01886
01887
01888
01889
01890 static int content_transformable(List *push_headers)
01891 {
01892 List *cache_directives;
01893 long i;
01894 Octstr *header_name,
01895 *header_value;
01896
01897 gw_assert(push_headers);
01898
01899 cache_directives = http_header_find_all(push_headers, "Cache-Control");
01900 if (gwlist_len(cache_directives) == 0) {
01901 http_destroy_headers(cache_directives);
01902 return 1;
01903 }
01904
01905 i = 0;
01906 while (i < gwlist_len(cache_directives)) {
01907 http_header_get(cache_directives, i, &header_name, &header_value);
01908 if (octstr_compare(header_value, octstr_imm("no-transform")) == 0) {
01909 http_destroy_headers(cache_directives);
01910 octstr_destroy(header_name);
01911 octstr_destroy(header_value);
01912 return 0;
01913 }
01914 ++i;
01915 }
01916
01917 http_destroy_headers(cache_directives);
01918 octstr_destroy(header_name);
01919 octstr_destroy(header_value);
01920
01921 return 1;
01922 }
01923
01924
01925
01926
01927
01928 static Octstr *convert_wml_to_wmlc(struct content *content)
01929 {
01930 Octstr *wmlc;
01931
01932 if (wml_compile(content->body, content->charset, &wmlc, NULL) == 0)
01933 return wmlc;
01934 warning(0, "PPG: wml compilation failed");
01935 return NULL;
01936 }
01937
01938 static Octstr *convert_si_to_sic(struct content *content)
01939 {
01940 Octstr *sic;
01941
01942 if (si_compile(content->body, content->charset, &sic) == 0)
01943 return sic;
01944 warning(0, "PPG: si compilation failed");
01945 return NULL;
01946 }
01947
01948 static Octstr *convert_sl_to_slc(struct content *content)
01949 {
01950 Octstr *slc;
01951
01952 if (sl_compile(content->body, content->charset, &slc) == 0)
01953 return slc;
01954 warning(0, "PPG: sl compilation failed");
01955 return NULL;
01956 }
01957
01958
01959 static Octstr *extract_base64(struct content *content)
01960 {
01961 Octstr *orig = octstr_duplicate(content->body);
01962 octstr_base64_to_binary(orig);
01963 return orig;
01964 }
01965
01966 static struct {
01967 char *type;
01968 char *result_type;
01969 Octstr *(*convert) (struct content *);
01970 } converters[] = {
01971 { "text/vnd.wap.wml",
01972 "application/vnd.wap.wmlc",
01973 convert_wml_to_wmlc },
01974 { "text/vnd.wap.si",
01975 "application/vnd.wap.sic",
01976 convert_si_to_sic },
01977 { "text/vnd.wap.sl",
01978 "application/vnd.wap.slc",
01979 convert_sl_to_slc}
01980 };
01981
01982 #define NUM_CONVERTERS ((long) (sizeof(converters) / sizeof(converters[0])))
01983
01984 static struct {
01985 char *transfer_encoding;
01986 Octstr *(*extract) (struct content *);
01987 } extractors[] = {
01988 { "base64",
01989 extract_base64 }
01990 };
01991
01992 #define NUM_EXTRACTORS ((long) (sizeof(extractors) / sizeof(extractors[0])))
01993
01994
01995
01996
01997
01998 static int pap_convert_content(struct content *content)
01999 {
02000 long i;
02001 Octstr *new_body;
02002
02003 for (i = 0; i < NUM_CONVERTERS; i++) {
02004 if (octstr_compare(content->type,
02005 octstr_imm(converters[i].type)) == 0) {
02006 new_body = converters[i].convert(content);
02007 if (new_body == NULL)
02008 return 0;
02009 octstr_destroy(content->body);
02010 content->body = new_body;
02011 octstr_destroy(content->type);
02012 content->type = octstr_create(converters[i].result_type);
02013 return 1;
02014 }
02015 }
02016
02017 return 1;
02018 }
02019
02020
02021
02022
02023
02024
02025 static int pap_get_content(struct content *content)
02026 {
02027 long i;
02028 Octstr *new_body;
02029
02030 for (i = 0; i < NUM_EXTRACTORS; i++) {
02031 if (octstr_case_compare(content->type,
02032 octstr_imm(extractors[i].transfer_encoding)) == 0) {
02033
02034 new_body = extractors[i].extract(content);
02035 if (new_body == NULL)
02036 return 0;
02037 octstr_destroy(content->body);
02038 content->body = new_body;
02039 octstr_destroy(content->type);
02040 content->type = NULL;
02041 return 1;
02042 }
02043 }
02044
02045 return 1;
02046 }
02047
02048
02049
02050
02051
02052 static char *bearers[] = {
02053 "Any",
02054 "SMS",
02055 "CSD",
02056 "GPRS",
02057 "Packet Data",
02058 "CDPD"
02059 };
02060
02061 #define NUMBER_OF_BEARERS sizeof(bearers)/sizeof(bearers[0])
02062
02063 static char *networks[] = {
02064 "Any",
02065 "GSM",
02066 "IS-95 CDMA",
02067 "ANSI-136",
02068 "AMPS",
02069 "PDC",
02070 "IDEN",
02071 "PHS",
02072 "TETRA"
02073 };
02074
02075 #define NUMBER_OF_NETWORKS sizeof(networks)/sizeof(networks[0])
02076
02077
02078
02079
02080
02081
02082
02083 int select_bearer_network(WAPEvent **e)
02084 {
02085 Octstr *bearer,
02086 *network;
02087 int bearer_required,
02088 network_required;
02089 size_t i,
02090 j;
02091
02092 gw_assert((**e).type == Push_Message);
02093
02094 bearer_required = (**e).u.Push_Message.bearer_required;
02095 network_required = (**e).u.Push_Message.network_required;
02096 bearer = octstr_imm("Any");
02097 network = octstr_imm("Any");
02098
02099 if (!bearer_required || !network_required)
02100 return 1;
02101
02102 if (bearer_required)
02103 bearer = (**e).u.Push_Message.bearer;
02104 if (network_required)
02105 network = (**e).u.Push_Message.network;
02106
02107 for (i = 0; i < NUMBER_OF_NETWORKS ; ++i) {
02108 if (octstr_case_compare(bearer, octstr_imm(bearers[i])) == 0)
02109 break;
02110 }
02111 for (j = 0; j < NUMBER_OF_BEARERS ; ++j) {
02112 if (octstr_case_compare(bearer, octstr_imm(bearers[j])) == 0)
02113 break;
02114 }
02115 if (i == NUMBER_OF_NETWORKS || j == NUMBER_OF_BEARERS)
02116 return 0;
02117
02118 return 1;
02119 }
02120
02121 static int session_has_pi_client_address(void *a, void *b)
02122 {
02123 Octstr *caddr;
02124 PPGSessionMachine *sm;
02125
02126 caddr = b;
02127 sm = a;
02128
02129 return octstr_compare(caddr, sm->pi_client_address) == 0;
02130 }
02131
02132
02133
02134
02135
02136 PPGSessionMachine *session_find_using_pi_client_address(Octstr *caddr)
02137 {
02138 PPGSessionMachine *sm;
02139
02140 sm = gwlist_search(ppg_machines, caddr, session_has_pi_client_address);
02141
02142 return sm;
02143 }
02144
02145
02146
02147
02148 static Octstr *tell_ppg_name(void)
02149 {
02150 return octstr_format("%S; WAP/1.3 (" GW_NAME "/%s)", get_official_name(),
02151 GW_VERSION);
02152 }
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162 static int delivery_time_constraints(WAPEvent *e, PPGPushMachine *pm)
02163 {
02164 Octstr *before,
02165 *after;
02166 struct tm now;
02167
02168 gw_assert(e->type = Push_Message);
02169
02170 before = e->u.Push_Message.deliver_before_timestamp;
02171 after = pm->deliver_after_timestamp;
02172 now = gw_gmtime(time(NULL));
02173
02174 if (!deliver_before_test_cleared(before, now)) {
02175 info(0, "PPG: delivery deadline expired, dropping the push message");
02176 return 0;
02177 }
02178
02179 if (!deliver_after_test_cleared(after, now)) {
02180 debug("wap.push.ppg", 0, "PPG: too early to push the message,"
02181 " waiting");
02182 return 1;
02183 }
02184
02185 return 2;
02186 }
02187
02188
02189
02190
02191
02192 struct description_t {
02193 long reason;
02194 char *description;
02195 };
02196
02197 typedef struct description_t description_t;
02198
02199 static description_t pap_desc[] = {
02200 { PAP_OK, "The request succeeded"},
02201 { PAP_ACCEPTED_FOR_PROCESSING, "The request has been accepted for"
02202 " processing"},
02203 { PAP_BAD_REQUEST, "Not understood due to malformed syntax"},
02204 { PAP_FORBIDDEN, "Request was refused"},
02205 { PAP_ADDRESS_ERROR, "The client specified not recognised"},
02206 { PAP_CAPABILITIES_MISMATCH, "Capabilities assumed by PI were not"
02207 " acceptable for the client specified"},
02208 { PAP_DUPLICATE_PUSH_ID, "Push id supplied was not unique"},
02209 { PAP_INTERNAL_SERVER_ERROR, "Server could not fulfill the request due"
02210 " to an internal error"},
02211 { PAP_TRANSFORMATION_FAILURE, "PPG was unable to perform a transformation"
02212 " of the message"},
02213 { PAP_REQUIRED_BEARER_NOT_AVAILABLE, "Required bearer not available"},
02214 { PAP_SERVICE_FAILURE, "The service failed. The client may re-attempt"
02215 " the operation"},
02216 { PAP_CLIENT_ABORTED, "The client aborted the operation. No reason given"},
02217 { WSP_ABORT_USERREQ, "Wsp requested abort"},
02218 { WSP_ABORT_USERRFS, "Wsp refused push message. Do not try again"},
02219 { WSP_ABORT_USERPND, "Push message cannot be delivered to intended"
02220 " destination by the wsp"},
02221 { WSP_ABORT_USERDCR, "Push message discarded due to resource shortage in"
02222 " wsp"},
02223 { WSP_ABORT_USERDCU, "Content type of the push message cannot be"
02224 " processed by the wsp"}
02225 };
02226
02227 static size_t desc_tab_size = sizeof(pap_desc) / sizeof(pap_desc[0]);
02228
02229 static Octstr *describe_code(long code)
02230 {
02231 Octstr *desc;
02232 size_t i;
02233
02234 for (i = 0; i < desc_tab_size; i++) {
02235 if (pap_desc[i].reason == code) {
02236 desc = octstr_create(pap_desc[i].description);
02237 return desc;
02238 }
02239 }
02240
02241 return octstr_imm("unknown PAP code");
02242 }
02243
02244
02245
02246
02247
02248 static void remove_push_data(PPGSessionMachine *sm, PPGPushMachine *pm,
02249 int cless)
02250 {
02251 push_machine_assert(pm);
02252
02253 if (cless) {
02254 gwlist_delete_equal(ppg_unit_pushes, pm);
02255 } else {
02256 session_machine_assert(sm);
02257 gwlist_delete_equal(sm->push_machines, pm);
02258 }
02259
02260 push_machine_destroy(pm);
02261 }
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273 static int store_push_data(PPGPushMachine **pm, PPGSessionMachine *sm,
02274 WAPEvent *e, WAPAddrTuple *tuple, int cless)
02275 {
02276 Octstr *pi_push_id;
02277 int duplicate_push_id;
02278
02279 gw_assert(e->type == Push_Message);
02280
02281 pi_push_id = e->u.Push_Message.pi_push_id;
02282
02283 duplicate_push_id = 0;
02284 if (((!cless) &&
02285 (find_ppg_push_machine_using_pi_push_id(sm, pi_push_id) != NULL)) ||
02286 ((cless) &&
02287 (find_unit_ppg_push_machine_using_pi_push_id(pi_push_id) != NULL)))
02288 duplicate_push_id = 1;
02289
02290 *pm = push_machine_create(e, tuple);
02291
02292 if (duplicate_push_id)
02293 return !duplicate_push_id;
02294
02295 if (!cless) {
02296 gwlist_append(sm->push_machines, *pm);
02297 debug("wap.push.ppg", 0, "PPG: store_push_data: push machine %ld"
02298 " appended to push list of sm machine %ld", (*pm)->push_id,
02299 sm->session_id);
02300 } else {
02301 gwlist_append(ppg_unit_pushes, *pm);
02302 debug("wap.push.ppg", 0, "PPG: store_push_data: push machine %ld"
02303 " appended to unit push list", (*pm)->push_id);
02304 }
02305
02306 return !duplicate_push_id;
02307 }
02308
02309
02310
02311
02312
02313 static void deliver_confirmed_push(long last, PPGPushMachine *pm,
02314 PPGSessionMachine *sm)
02315 {
02316 request_confirmed_push(last, pm, sm);
02317 }
02318
02319
02320
02321
02322
02323
02324
02325
02326 static PPGPushMachine *deliver_unit_push(long last, PPGPushMachine *pm,
02327 PPGSessionMachine *sm, int session_exists)
02328 {
02329 push_machine_assert(pm);
02330
02331 if (!session_exists)
02332 request_unit_push(last, pm);
02333 else
02334 request_push(last, pm);
02335
02336 pm = update_push_data_with_attribute(&sm, pm, PAP_UNCONFIRMED,
02337 PAP_DELIVERED1);
02338 info(0, "PPG: unconfirmed push delivered to OTA");
02339
02340 return pm;
02341 }
02342
02343
02344
02345
02346
02347 static void deliver_pending_pushes(PPGSessionMachine *sm, int last)
02348 {
02349 PPGPushMachine *pm;
02350 long i;
02351
02352 session_machine_assert(sm);
02353 gw_assert(gwlist_len(sm->push_machines) > 0);
02354
02355 i = 0;
02356 while (i < gwlist_len(sm->push_machines)) {
02357 pm = gwlist_get(sm->push_machines, i);
02358 push_machine_assert(pm);
02359
02360 if (pm->delivery_method == PAP_UNCONFIRMED) {
02361 request_push(last, pm);
02362 pm = update_push_data_with_attribute(&sm, pm, PAP_UNCONFIRMED,
02363 PAP_DELIVERED1);
02364 remove_push_data(sm, pm, sm == NULL);
02365 } else {
02366 request_confirmed_push(last, pm, sm);
02367 ++i;
02368 }
02369 }
02370 }
02371
02372
02373
02374
02375
02376 static PPGPushMachine *abort_delivery(PPGSessionMachine *sm, int status)
02377 {
02378 PPGPushMachine *pm;
02379 long reason,
02380 code;
02381
02382 session_machine_assert(sm);
02383
02384 pm = NULL;
02385 reason = PAP_ABORT_USERPND;
02386 code = PAP_CAPABILITIES_MISMATCH;
02387
02388 while (gwlist_len(sm->push_machines) > 0) {
02389 pm = gwlist_get(sm->push_machines, 0);
02390 push_machine_assert(pm);
02391
02392 pm = update_push_data_with_attribute(&sm, pm, reason, PAP_ABORTED);
02393 response_push_message(pm, code, status);
02394
02395 remove_push_data(sm, pm, sm == NULL);
02396 }
02397
02398 return pm;
02399 }
02400
02401
02402
02403
02404
02405
02406 static void remove_session_data(PPGSessionMachine *sm, int status)
02407 {
02408 long code;
02409 PPGPushMachine *pm;
02410
02411 session_machine_assert(sm);
02412
02413 code = PAP_ABORT_USERPND;
02414
02415 while (gwlist_len(sm->push_machines) > 0) {
02416 pm = gwlist_get(sm->push_machines, 0);
02417 response_push_message(pm, code, status);
02418 remove_push_data(sm, pm, sm == NULL);
02419 }
02420
02421 gwlist_delete_equal(ppg_machines, sm);
02422 session_machine_destroy(sm);
02423 }
02424
02425
02426
02427
02428 static void remove_pushless_session(PPGSessionMachine *sm)
02429 {
02430 session_machine_assert(sm);
02431
02432 if (gwlist_len(sm->push_machines) == 0) {
02433 gwlist_delete_equal(ppg_machines, sm);
02434 session_machine_destroy(sm);
02435 }
02436 }
02437
02438
02439
02440
02441
02442
02443
02444
02445 static PPGSessionMachine *store_session_data(PPGSessionMachine *sm,
02446 WAPEvent *e, WAPAddrTuple *tuple, int *session_exists)
02447 {
02448 gw_assert(e->type == Push_Message);
02449
02450 if (sm == NULL) {
02451 sm = session_machine_create(tuple, e);
02452 *session_exists = 0;
02453 } else
02454 *session_exists = 1;
02455
02456 return sm;
02457 }
02458
02459 static PPGSessionMachine *update_session_data_with_headers(
02460 PPGSessionMachine *sm, PPGPushMachine *pm)
02461 {
02462 gwlist_delete_matching(sm->push_machines, &pm->push_id, push_has_pid);
02463 gwlist_append(sm->push_machines, pm);
02464
02465 return sm;
02466 }
02467
02468
02469
02470
02471
02472
02473
02474 static int confirmation_requested(WAPEvent *e)
02475 {
02476 gw_assert(e->type = Push_Message);
02477
02478 return e->u.Push_Message.delivery_method == PAP_CONFIRMED ||
02479 e->u.Push_Message.delivery_method == PAP_PREFERCONFIRMED;
02480 }
02481
02482 static int push_has_pid(void *a, void *b)
02483 {
02484 long *pid;
02485 PPGPushMachine *pm;
02486
02487 pid = b;
02488 pm = a;
02489
02490 return *pid == pm->push_id;
02491 }
02492
02493 static PPGPushMachine *find_ppg_push_machine_using_pid(PPGSessionMachine *sm,
02494 long pid)
02495 {
02496 PPGPushMachine *pm;
02497
02498 gw_assert(pid >= 0);
02499 session_machine_assert(sm);
02500
02501 pm = gwlist_search(sm->push_machines, &pid, push_has_pid);
02502
02503 return pm;
02504 }
02505
02506 static int push_has_pi_push_id(void *a, void *b)
02507 {
02508 Octstr *pi_push_id;
02509 PPGPushMachine *pm;
02510
02511 pi_push_id = b;
02512 pm = a;
02513
02514 return octstr_compare(pm->pi_push_id, pi_push_id) == 0;
02515 }
02516
02517 static PPGPushMachine *find_ppg_push_machine_using_pi_push_id(
02518 PPGSessionMachine *sm, Octstr *pi_push_id)
02519 {
02520 PPGPushMachine *pm;
02521
02522 gw_assert(pi_push_id);
02523 session_machine_assert(sm);
02524
02525 pm = gwlist_search(sm->push_machines, pi_push_id, push_has_pi_push_id);
02526
02527 return pm;
02528 }
02529
02530 static PPGPushMachine *find_unit_ppg_push_machine_using_pi_push_id(
02531 Octstr *pi_push_id)
02532 {
02533 PPGPushMachine *pm;
02534
02535 gw_assert(pi_push_id);
02536 pm = gwlist_search(ppg_unit_pushes, pi_push_id, push_has_pi_push_id);
02537
02538 return pm;
02539 }
02540
02541
02542
02543
02544
02545
02546
02547
02548 static PPGPushMachine *update_push_data_with_attribute(PPGSessionMachine **sm,
02549 PPGPushMachine *qm, long reason, long status)
02550 {
02551 push_machine_assert(qm);
02552
02553 switch (status) {
02554 case PAP_UNDELIVERABLE1:
02555 qm->message_state = PAP_UNDELIVERABLE;
02556 qm->code = PAP_BAD_REQUEST;
02557 break;
02558
02559 case PAP_UNDELIVERABLE2:
02560 qm->code = reason;
02561 qm->message_state = PAP_UNDELIVERABLE;
02562 qm->desc = describe_code(reason);
02563 break;
02564
02565 case PAP_ABORTED:
02566 qm->message_state = status;
02567 qm->code = ota_abort_to_pap(reason);
02568 qm->event_time = set_time();
02569 qm->desc = describe_code(reason);
02570 break;
02571
02572 case PAP_DELIVERED1:
02573 qm->message_state = PAP_DELIVERED;
02574 qm->delivery_method = PAP_UNCONFIRMED;
02575 qm->event_time = set_time();
02576 break;
02577
02578 case PAP_DELIVERED2:
02579 qm->message_state = PAP_DELIVERED;
02580 qm->delivery_method = PAP_CONFIRMED;
02581 qm->event_time = set_time();
02582 break;
02583
02584 case PAP_EXPIRED:
02585 qm->message_state = PAP_EXPIRED;
02586 qm->event_time = set_time();
02587 qm->desc = describe_code(reason);
02588 break;
02589
02590 case PAP_PENDING:
02591 qm->message_state = PAP_PENDING;
02592 break;
02593
02594 default:
02595 error(0, "WAP_PUSH_PPG: update_push_data_with_attribute: Non"
02596 " existing push machine status: %ld", status);
02597 break;
02598 }
02599
02600 if (*sm != NULL){
02601 gwlist_delete_matching((**sm).push_machines, &qm->push_id, push_has_pid);
02602 gwlist_append((**sm).push_machines, qm);
02603 gwlist_delete_equal(ppg_machines, *sm);
02604 gwlist_append(ppg_machines, *sm);
02605 } else {
02606 gwlist_delete_matching(ppg_unit_pushes, &qm->push_id, push_has_pid);
02607 gwlist_append(ppg_unit_pushes, qm);
02608 }
02609
02610 return qm;
02611 }
02612
02613
02614
02615
02616 static PPGSessionMachine *update_session_data(PPGSessionMachine *m,
02617 long sid, long port, List *caps)
02618 {
02619 session_machine_assert(m);
02620 gw_assert(sid >= 0);
02621
02622 m->session_id = sid;
02623 m->addr_tuple->remote->port = port;
02624 m->client_capabilities = wsp_cap_duplicate_list(caps);
02625
02626 gwlist_delete_equal(ppg_machines, m);
02627 gwlist_append(ppg_machines, m);
02628
02629 return m;
02630 }
02631
02632
02633
02634
02635
02636 static long ota_abort_to_pap(long reason)
02637 {
02638 long offset;
02639
02640 offset = reason - 0xEA;
02641 reason = 5026 + offset;
02642
02643 return reason;
02644 }
02645
02646
02647
02648
02649
02650 static int cless_accepted(WAPEvent *e, PPGSessionMachine *sm)
02651 {
02652 gw_assert(e->type == Push_Message);
02653 return (e->u.Push_Message.delivery_method == PAP_UNCONFIRMED ||
02654 e->u.Push_Message.delivery_method == PAP_NOT_SPECIFIED) &&
02655 (sm == NULL);
02656 }
02657
02658
02659
02660
02661 static int coriented_deliverable(long appid_code)
02662 {
02663 return appid_code > -1;
02664 }
02665
02666
02667
02668
02669
02670
02671
02672
02673 static void initialize_time_item_array(long time_data[], struct tm now)
02674 {
02675 time_data[0] = now.tm_year + 1900;
02676 time_data[1] = now.tm_mon + 1;
02677 time_data[2] = now.tm_mday;
02678 time_data[3] = now.tm_hour;
02679 time_data[4] = now.tm_min;
02680 time_data[5] = now.tm_sec;
02681 }
02682
02683 static int date_item_compare(Octstr *condition, long time_data, long pos)
02684 {
02685 long data;
02686
02687 if (octstr_parse_long(&data, condition, pos, 10) < 0) {
02688 return 0;
02689 }
02690 if (data < time_data) {
02691 return -1;
02692 }
02693 if (data > time_data) {
02694 return 1;
02695 }
02696
02697 return 0;
02698 }
02699
02700
02701
02702
02703
02704 static int deliver_before_test_cleared(Octstr *before, struct tm now)
02705 {
02706 long time_data[6];
02707 long j;
02708
02709 if (before == NULL)
02710 return 1;
02711
02712 initialize_time_item_array(time_data, now);
02713 if (date_item_compare(before, time_data[0], 0) == 1)
02714 return 1;
02715 if (date_item_compare(before, time_data[0], 0) == -1)
02716 return 0;
02717
02718 for (j = 5; j < octstr_len(before); j += 3) {
02719 if (date_item_compare(before, time_data[(j-5)/3 + 1], j) == 1)
02720 return 1;
02721 if (date_item_compare(before, time_data[(j-5)/3 + 1], j) == -1)
02722 return 0;
02723 }
02724
02725 return 0;
02726 }
02727
02728
02729
02730
02731
02732 static int deliver_after_test_cleared(Octstr *after, struct tm now)
02733 {
02734 long time_data[6];
02735 long j;
02736
02737 if (after == NULL)
02738 return 1;
02739
02740 initialize_time_item_array(time_data, now);
02741 if (date_item_compare(after, time_data[0], 0) == -1)
02742 return 1;
02743 if (date_item_compare(after, time_data[0], 0) == 1)
02744 return 0;
02745
02746 for (j = 5; j < octstr_len(after); j += 3) {
02747 if (date_item_compare(after, time_data[(j-5)/3 + 1], j) == -1)
02748 return 1;
02749 if (date_item_compare(after, time_data[(j-5)/3 + 1], j) == 1)
02750 return 0;
02751 }
02752
02753 return 0;
02754 }
02755
02756
02757
02758
02759
02760
02761
02762 static WAPAddrTuple *set_addr_tuple(Octstr *address, long cliport, long servport,
02763 long address_type, List *push_headers)
02764 {
02765 Octstr *cliaddr;
02766 Octstr *from = NULL;
02767 WAPAddrTuple *tuple;
02768
02769 gw_assert(address);
02770
02771 if (address_type == ADDR_PLMN) {
02772 from = http_header_value(push_headers, octstr_imm("X-Kannel-From"));
02773 cliaddr = from ? from : global_sender;
02774 } else {
02775 cliaddr = octstr_imm("0.0.0.0");
02776 }
02777
02778 tuple = wap_addr_tuple_create(address, cliport, cliaddr, servport);
02779
02780 octstr_destroy(from);
02781 http_header_remove_all(push_headers, "X-Kannel-From");
02782
02783 return tuple;
02784 }
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796 static char *wina_uri[] =
02797 { "*",
02798 "push.sia",
02799 "wml.ua",
02800 "wta.ua",
02801 "mms.ua",
02802 "push.syncml",
02803 "loc.ua",
02804 "syncml.dm",
02805 "drm.ua",
02806 "emn.ua",
02807 "wv.ua",
02808 "x-wap-microsoft:localcontent.ua",
02809 "x-wap-microsoft:IMclient.ua",
02810 "x-wap-docomo:imode.mail.ua",
02811 "x-wap-docomo:imode.mr.ua",
02812 "x-wap-docomo:imode.mf.ua",
02813 "x-motorola:location.ua",
02814 "x-motorola:now.ua",
02815 "x-motorola:otaprov.ua",
02816 "x-motorola:browser.ua",
02817 "x-motorola:splash.ua",
02818 "x-wap-nai:mvsw.command",
02819 "x-wap-openwave:iota.ua",
02820 "x-wap-docomo:imode.mail2.ua",
02821 "x-oma-nec:otaprov.ua",
02822 "x-oma-nokia:call.ua"
02823 };
02824
02825 #define NUMBER_OF_WINA_URIS sizeof(wina_uri)/sizeof(wina_uri[0])
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836 static long parse_appid_header(Octstr **appid_content)
02837 {
02838 long pos,
02839 coded_value;
02840 size_t i;
02841
02842 if ((pos = octstr_search(*appid_content, octstr_imm(";"), 0)) >= 0) {
02843 octstr_delete(*appid_content, pos,
02844 octstr_len(octstr_imm(";app-encoding=")));
02845 octstr_delete(*appid_content, 0, pos);
02846 return -1;
02847 }
02848
02849 i = 0;
02850 while (i < NUMBER_OF_WINA_URIS) {
02851 if ((pos = octstr_case_search(*appid_content,
02852 octstr_imm(wina_uri[i]), 0)) >= 0)
02853 break;
02854 ++i;
02855 }
02856
02857 if (i == NUMBER_OF_WINA_URIS) {
02858 octstr_destroy(*appid_content);
02859 *appid_content = octstr_format("%ld", 2);
02860 return -1;
02861 }
02862
02863 octstr_delete(*appid_content, 0, pos);
02864 if ((coded_value = wsp_string_to_application_id(*appid_content)) >= 0) {
02865 octstr_destroy(*appid_content);
02866 *appid_content = octstr_format("%ld", coded_value);
02867 return coded_value;
02868 }
02869
02870 return -1;
02871 }
02872
02873 static WAPAddrTuple *addr_tuple_change_cliport(WAPAddrTuple *tuple, long port)
02874 {
02875 WAPAddrTuple *dubble;
02876
02877 if (tuple == NULL)
02878 return NULL;
02879
02880 dubble = wap_addr_tuple_create(tuple->remote->address,
02881 port,
02882 tuple->local->address,
02883 tuple->local->port);
02884
02885 return dubble;
02886 }
02887
02888
02889
02890
02891
02892
02893
02894
02895 static int headers_acceptable(List *push_headers, Octstr **content_header)
02896 {
02897 gw_assert(push_headers);
02898 *content_header = http_header_find_first(push_headers, "Content-Type");
02899
02900 if (*content_header == NULL) {
02901 *content_header = octstr_format("%s", "no content type header found");
02902 goto error;
02903 }
02904
02905 if (!type_is(*content_header, "multipart/related")) {
02906 goto error;
02907 }
02908
02909 if (!type_is(*content_header, "application/xml")) {
02910 goto error;
02911 }
02912
02913 return 1;
02914
02915 error:
02916 warning(0, "PPG: headers_acceptable: got unacceptable push headers");
02917 return 0;
02918 }
02919
02920
02921
02922
02923
02924
02925
02926 static int type_is(Octstr *content_header, char *name)
02927 {
02928 Octstr *quoted_type,
02929 *osname;
02930
02931 osname = octstr_imm(name);
02932 if (octstr_case_search(content_header, osname, 0) >= 0)
02933 return 1;
02934
02935 quoted_type = octstr_format("\"%S\"", osname);
02936
02937 if (octstr_case_search(content_header, quoted_type, 0) >= 0) {
02938 octstr_destroy(quoted_type);
02939 return 1;
02940 }
02941
02942 octstr_destroy(quoted_type);
02943 return 0;
02944 }
02945
02946
02947
02948
02949
02950 static int get_mime_boundary(List *push_headers, Octstr *content_header,
02951 Octstr **boundary)
02952 {
02953 long pos;
02954 Octstr *bos;
02955 int c, quoted = 0;
02956 long bstart;
02957
02958 pos = 0;
02959 if ((pos = octstr_case_search(content_header,
02960 bos = octstr_imm("boundary="), 0)) < 0) {
02961 warning(0, "PPG: get_mime_boundary: no boundary specified");
02962 return -1;
02963 }
02964
02965 pos += octstr_len(bos);
02966 if (octstr_get_char(content_header, pos) == '"') {
02967 ++pos;
02968 quoted = 1;
02969 }
02970
02971 bstart = pos;
02972 while ((c = octstr_get_char(content_header, pos)) != -1) {
02973 if (c == ';' || (quoted && c == '"') || (!quoted && c == ' '))
02974 break;
02975 ++pos;
02976 }
02977 *boundary = octstr_copy(content_header, bstart, pos - bstart);
02978
02979 return 0;
02980 }
02981
02982 static void change_header_value(List **push_headers, char *name, char *value)
02983 {
02984 http_header_remove_all(*push_headers, name);
02985 http_header_add(*push_headers, name, value);
02986 }
02987
02988
02989
02990
02991
02992 static void remove_mime_headers(List **push_headers)
02993 {
02994 http_header_remove_all(*push_headers, "MIME-Version");
02995 }
02996
02997
02998
02999
03000 static void remove_link_headers(List **push_headers)
03001 {
03002 http_header_remove_all(*push_headers, "Host");
03003 }
03004
03005
03006
03007
03008 static void remove_x_kannel_headers(List **push_headers)
03009 {
03010 http_header_remove_all(*push_headers, "X-Kannel-SMSC");
03011 http_header_remove_all(*push_headers, "X-Kannel-DLR-Url");
03012 http_header_remove_all(*push_headers, "X-Kannel-DLR-Mask");
03013 http_header_remove_all(*push_headers, "X-Kannel-Smsbox-Id");
03014 }
03015
03016
03017
03018
03019
03020
03021 static void send_bad_message_response(HTTPClient **c, Octstr *fragment,
03022 int code, int status)
03023 {
03024 Octstr *reply_body;
03025
03026 reply_body = octstr_format("%s",
03027 "<?xml version=\"1.0\"?>"
03028 "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 1.0//EN\""
03029 " \"http://www.wapforum.org/DTD/pap_1.0.dtd\">"
03030 "<pap>"
03031 "<badmessage-response code=\"");
03032 octstr_format_append(reply_body, "%d", code);
03033 octstr_format_append(reply_body, "%s", "\""
03034 " desc=\"");
03035 octstr_format_append(reply_body, "%s", "Not understood due to malformed"
03036 " syntax");
03037 octstr_format_append(reply_body, "%s", "\"");
03038
03039 if (fragment != NULL && octstr_len(fragment) != 0) {
03040 octstr_format_append(reply_body, "%s", " bad-message-fragment=\"");
03041 octstr_format_append(reply_body, "%S", escape_fragment(fragment));
03042 octstr_format_append(reply_body, "%s", "\"");
03043 }
03044
03045 octstr_format_append(reply_body, "%s", ">"
03046 "</badmessage-response>"
03047 "</pap>");
03048
03049 debug("wap.push.ppg", 0, "PPG: send_bad_message_response: telling pi");
03050 send_to_pi(c, reply_body, status);
03051
03052 octstr_destroy(fragment);
03053 }
03054
03055
03056
03057
03058
03059
03060
03061 static HTTPClient *send_push_response(WAPEvent *e, int status)
03062 {
03063 Octstr *reply_body,
03064 *url;
03065 HTTPClient *c;
03066
03067 gw_assert(e->type == Push_Response);
03068 url = dict_get(urls, e->u.Push_Response.pi_push_id);
03069 dict_remove(urls, e->u.Push_Response.pi_push_id);
03070
03071 reply_body = octstr_format("%s",
03072 "<?xml version=\"1.0\"?>"
03073 "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 1.0//EN\""
03074 " \"http://www.wapforum.org/DTD/pap_1.0.dtd\">"
03075 "<pap>"
03076 "<push-response push-id=\"");
03077 octstr_format_append(reply_body, "%S", e->u.Push_Response.pi_push_id);
03078 octstr_format_append(reply_body, "%s", "\"");
03079
03080 if (e->u.Push_Response.sender_name != NULL) {
03081 octstr_format_append(reply_body, "%s",
03082 " sender-name=\"");
03083 octstr_format_append(reply_body, "%S",
03084 e->u.Push_Response.sender_name);
03085 octstr_format_append(reply_body, "%s", "\"");
03086 }
03087
03088 if (e->u.Push_Response.reply_time != NULL) {
03089 octstr_format_append(reply_body, "%s",
03090 " reply-time=\"");
03091 octstr_format_append(reply_body, "%S",
03092 e->u.Push_Response.reply_time);
03093 octstr_format_append(reply_body, "%s", "\"");
03094 }
03095
03096 if (url != NULL) {
03097 octstr_format_append(reply_body, "%s",
03098 " sender-address=\"");
03099 octstr_format_append(reply_body, "%S", url);
03100 octstr_format_append(reply_body, "%s", "\"");
03101 }
03102
03103 octstr_format_append(reply_body, "%s", ">"
03104 "<response-result code =\"");
03105 octstr_format_append(reply_body, "%d", e->u.Push_Response.code);
03106 octstr_format_append(reply_body, "%s", "\"");
03107
03108 if (e->u.Push_Response.desc != NULL) {
03109 octstr_format_append(reply_body, "%s", " desc=\"");
03110 octstr_format_append(reply_body, "%S", e->u.Push_Response.desc);
03111 octstr_format_append(reply_body, "\"");
03112 }
03113
03114 octstr_format_append(reply_body, "%s", ">"
03115 "</response-result>"
03116 "</push-response>"
03117 "</pap>");
03118
03119 octstr_destroy(url);
03120
03121 c = dict_get(http_clients, e->u.Push_Response.pi_push_id);
03122 dict_remove(http_clients, e->u.Push_Response.pi_push_id);
03123
03124 debug("wap.push.ppg", 0, "PPG: send_push_response: telling pi");
03125 send_to_pi(&c, reply_body, status);
03126
03127 wap_event_destroy(e);
03128 return c;
03129 }
03130
03131
03132
03133
03134
03135
03136 static void tell_fatal_error(HTTPClient **c, WAPEvent *e, Octstr *url,
03137 int status, int code)
03138 {
03139 Octstr *reply_body,
03140 *dos,
03141 *tos,
03142 *sos;
03143
03144 gw_assert(e->type == Push_Message);
03145 reply_body = octstr_format("%s",
03146 "<?xml version=\"1.0\"?>"
03147 "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 1.0//EN\""
03148 " \"http://www.wapforum.org/DTD/pap_1.0.dtd\">"
03149 "<pap>"
03150 "<push-response push-id=\"");
03151 octstr_format_append(reply_body, "%S", e->u.Push_Message.pi_push_id);
03152 octstr_format_append(reply_body, "%s", "\"");
03153
03154 octstr_format_append(reply_body, "%s",
03155 " sender-name=\"");
03156 octstr_format_append(reply_body, "%S", tos = tell_ppg_name());
03157 octstr_format_append(reply_body, "%s", "\"");
03158
03159 octstr_format_append(reply_body, "%s",
03160 " reply-time=\"");
03161 octstr_format_append(reply_body, "%S", sos = set_time());
03162 octstr_format_append(reply_body, "%s", "\"");
03163
03164 octstr_format_append(reply_body, "%s",
03165 " sender-address=\"");
03166 octstr_format_append(reply_body, "%S", url);
03167 octstr_format_append(reply_body, "%s", "\"");
03168
03169 octstr_format_append(reply_body, "%s", ">"
03170 "<response-result code =\"");
03171 octstr_format_append(reply_body, "%d", code);
03172 octstr_format_append(reply_body, "%s", "\"");
03173
03174 octstr_format_append(reply_body, "%s", " desc=\"");
03175 octstr_format_append(reply_body, "%S", dos = describe_code(code));
03176 octstr_format_append(reply_body, "\"");
03177
03178 octstr_format_append(reply_body, "%s", ">"
03179 "</response-result>"
03180 "</push-response>"
03181 "</pap>");
03182
03183 debug("wap.push.ppg", 0, "PPG: tell_fatal_error: %s", octstr_get_cstr(dos));
03184 send_to_pi(c, reply_body, status);
03185
03186 octstr_destroy(dos);
03187 octstr_destroy(tos);
03188 octstr_destroy(sos);
03189 wap_event_destroy(e);
03190 }
03191
03192
03193
03194
03195
03196 static void send_to_pi(HTTPClient **c, Octstr *reply_body, int status) {
03197 List *reply_headers;
03198
03199 reply_headers = http_create_empty_headers();
03200 http_header_add(reply_headers, "Content-Type", "application/xml");
03201
03202 if (*c != NULL)
03203 http_send_reply(*c, status, reply_headers, reply_body);
03204
03205 octstr_destroy(reply_body);
03206 http_destroy_headers(reply_headers);
03207 }
03208
03209
03210
03211
03212
03213
03214 static Octstr *escape_fragment(Octstr *fragment)
03215 {
03216 long i;
03217 int c;
03218
03219 i = 0;
03220 while (i < octstr_len(fragment)) {
03221 if ((c = octstr_get_char(fragment, i)) == '"') {
03222 replace_octstr_char(fragment, octstr_imm("""), &i);
03223 } else if (c == '<') {
03224 replace_octstr_char(fragment, octstr_imm("<"), &i);
03225 } else if (c == '>') {
03226 replace_octstr_char(fragment, octstr_imm(">"), &i);
03227 } else if (c == '&') {
03228 replace_octstr_char(fragment, octstr_imm("&"), &i);
03229 }
03230 ++i;
03231 }
03232
03233 return fragment;
03234 }
03235
03236 static int is_phone_number(long address_type)
03237 {
03238 return address_type == ADDR_PLMN;
03239 }
03240
03241 static void replace_octstr_char(Octstr *os1, Octstr *os2, long *pos)
03242 {
03243 octstr_delete(os1, *pos, 1);
03244 octstr_insert(os1, os2, *pos);
03245 *pos += octstr_len(os2) - 1;
03246 }
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256 static Octstr *set_smsc_id(List *headers, Octstr *username, int trusted_pi)
03257 {
03258 Octstr *smsc_id = NULL;
03259
03260 smsc_id = http_header_value(headers, octstr_imm("X-Kannel-SMSC"));
03261 if (smsc_id) {
03262 return smsc_id;
03263 }
03264
03265 if (!trusted_pi)
03266 smsc_id = wap_push_ppg_pushuser_smsc_id_get(username);
03267
03268 smsc_id = smsc_id ?
03269 smsc_id : (ppg_default_smsc ? octstr_duplicate(ppg_default_smsc) : NULL);
03270
03271 return smsc_id;
03272 }
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282 static Octstr *set_dlr_url(List *headers, Octstr *username, int trusted_pi)
03283 {
03284 Octstr *dlr_url = NULL;
03285
03286 dlr_url = http_header_value(headers, octstr_imm("X-Kannel-DLR-Url"));
03287 if (dlr_url) {
03288 return dlr_url;
03289 }
03290
03291 if (!trusted_pi)
03292 dlr_url = wap_push_ppg_pushuser_dlr_url_get(username);
03293
03294 dlr_url = dlr_url ?
03295 dlr_url : (ppg_dlr_url ? octstr_duplicate(ppg_dlr_url) : NULL);
03296
03297 return dlr_url;
03298 }
03299
03300
03301
03302
03303
03304
03305 static long set_dlr_mask(List *headers, Octstr *dlr_url)
03306 {
03307 Octstr *dlrmaskos;
03308 long dlr_mask;
03309 long masklen;
03310
03311 if (dlr_url == NULL) {
03312 return 0;
03313 }
03314
03315 dlrmaskos = http_header_value(headers, octstr_imm("X-Kannel-DLR-Mask"));
03316 if (dlrmaskos == NULL) {
03317 return 0;
03318 }
03319
03320 if ((masklen = octstr_parse_long(&dlr_mask, dlrmaskos, 0, 10)) != -1 &&
03321 masklen == octstr_len(dlrmaskos) &&
03322 dlr_mask >= -1 && dlr_mask <= 31) {
03323 octstr_destroy(dlrmaskos);
03324 return dlr_mask;
03325 }
03326
03327 warning(0, "unparsable dlr mask, rejected");
03328 octstr_destroy(dlrmaskos);
03329 return 0;
03330 }
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341 static Octstr *set_smsbox_id(List *headers, Octstr *username, int trusted_pi)
03342 {
03343 Octstr *smsbox_id = NULL;
03344
03345 smsbox_id = http_header_value(headers, octstr_imm("X-Kannel-Smsbox-Id"));
03346 if (smsbox_id != NULL) {
03347 return smsbox_id;
03348 }
03349
03350 if (!trusted_pi)
03351 smsbox_id = wap_push_ppg_pushuser_smsbox_id_get(username);
03352
03353 smsbox_id = smsbox_id ?
03354 smsbox_id : (ppg_smsbox_id ? octstr_duplicate(ppg_smsbox_id) : NULL);
03355
03356 return smsbox_id;
03357
03358 }
03359
03360
03361
03362
03363 static Octstr *set_service_name(void)
03364 {
03365 return octstr_duplicate(service_name);
03366 }
03367
03368
03369
03370
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.