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 #include <errno.h>
00079
00080 #include "wap_push_ota.h"
00081 #include "gwlib/gwlib.h"
00082 #include "wap/wsp.h"
00083 #include "wap/wsp_strings.h"
00084 #include "wap/wsp_pdu.h"
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 static enum {limbo, running, terminating} run_status = limbo;
00102
00103
00104
00105
00106 struct BearerboxAddress {
00107 Octstr *address;
00108 Mutex *mutex;
00109 };
00110 typedef struct BearerboxAddress BearerboxAddress;
00111
00112 static BearerboxAddress *bearerbox = NULL;
00113
00114 static List *ota_queue = NULL;
00115
00116 wap_dispatch_func_t *dispatch_to_wsp;
00117 wap_dispatch_func_t *dispatch_to_wsp_unit;
00118
00119
00120
00121
00122
00123
00124 static void main_thread(void *arg);
00125 static void handle_ota_event(WAPEvent *e);
00126 static void make_session_request(WAPEvent *e);
00127 static void make_push_request(WAPEvent *e);
00128 static void make_confirmed_push_request(WAPEvent *e);
00129 static void make_unit_push_request(WAPEvent *e);
00130 static void abort_push(WAPEvent *e);
00131
00132
00133
00134
00135 static List *add_push_flag(WAPEvent *e);
00136
00137
00138
00139
00140
00141
00142 static void check_session_request_headers(List *headers);
00143
00144
00145
00146
00147
00148 static Octstr *pack_sia(List *headers);
00149 static void flags_assert(WAPEvent *e);
00150 static void reason_assert(long reason);
00151 static Octstr *pack_server_address(void);
00152 static Octstr *pack_appid_list(List *headers);
00153
00154
00155
00156
00157 static Octstr *name(Octstr *os);
00158 static BearerboxAddress *bearerbox_address_create(void);
00159 static void bearerbox_address_destroy(BearerboxAddress *ba);
00160
00161
00162
00163
00164
00165
00166 void wap_push_ota_init(wap_dispatch_func_t *wsp_dispatch,
00167 wap_dispatch_func_t *wsp_unit_dispatch)
00168 {
00169 ota_queue = gwlist_create();
00170 gwlist_add_producer(ota_queue);
00171
00172 dispatch_to_wsp = wsp_dispatch;
00173 dispatch_to_wsp_unit = wsp_unit_dispatch;
00174
00175 bearerbox = bearerbox_address_create();
00176
00177 gw_assert(run_status == limbo);
00178 run_status = running;
00179 gwthread_create(main_thread, NULL);
00180 }
00181
00182 void wap_push_ota_shutdown(void)
00183 {
00184 gw_assert(run_status == running);
00185 run_status = terminating;
00186 gwlist_remove_producer(ota_queue);
00187 gwthread_join_every(main_thread);
00188
00189 gwlist_destroy(ota_queue, wap_event_destroy_item);
00190 bearerbox_address_destroy(bearerbox);
00191 }
00192
00193 void wap_push_ota_dispatch_event(WAPEvent *e)
00194 {
00195 gw_assert(run_status == running);
00196 gwlist_produce(ota_queue, e);
00197 }
00198
00199
00200
00201
00202
00203 void wap_push_ota_bb_address_set(Octstr *in)
00204 {
00205 gw_assert(in);
00206
00207 mutex_lock(bearerbox->mutex);
00208 bearerbox->address = name(in);
00209 mutex_unlock(bearerbox->mutex);
00210 }
00211
00212
00213
00214
00215
00216
00217 static void main_thread(void *arg)
00218 {
00219 WAPEvent *e;
00220
00221 while (run_status == running && (e = gwlist_consume(ota_queue)) != NULL) {
00222 handle_ota_event(e);
00223 }
00224
00225 }
00226
00227 static void handle_ota_event(WAPEvent *e)
00228 {
00229 debug("wap.push.ota", 0, "OTA: event arrived");
00230
00231 switch (e->type) {
00232 case Pom_SessionRequest_Req:
00233 make_session_request(e);
00234 break;
00235
00236 case Po_Push_Req:
00237 make_push_request(e);
00238 break;
00239
00240 case Po_ConfirmedPush_Req:
00241 make_confirmed_push_request(e);
00242 break;
00243
00244 case Po_Unit_Push_Req:
00245 make_unit_push_request(e);
00246 break;
00247
00248 case Po_PushAbort_Req:
00249 abort_push(e);
00250 break;
00251
00252 default:
00253 debug("wap.push.ota", 0, "OTA: unhandled event");
00254 wap_event_dump(e);
00255 break;
00256 }
00257
00258 wap_event_destroy(e);
00259 }
00260
00261 static void make_session_request(WAPEvent *e)
00262 {
00263 WAPEvent *wsp_event;
00264 List *appid_headers, *push_headers;
00265
00266 gw_assert(e->type == Pom_SessionRequest_Req);
00267 push_headers = e->u.Pom_SessionRequest_Req.push_headers;
00268
00269 check_session_request_headers(push_headers);
00270
00271 wsp_event = wap_event_create(S_Unit_Push_Req);
00272 wsp_event->u.S_Unit_Push_Req.address_type =
00273 e->u.Pom_SessionRequest_Req.address_type;
00274 if (e->u.Pom_SessionRequest_Req.smsc_id != NULL)
00275 wsp_event->u.S_Unit_Push_Req.smsc_id =
00276 octstr_duplicate(e->u.Pom_SessionRequest_Req.smsc_id);
00277 else
00278 wsp_event->u.S_Unit_Push_Req.smsc_id = NULL;
00279 if (e->u.Pom_SessionRequest_Req.dlr_url != NULL)
00280 wsp_event->u.S_Unit_Push_Req.dlr_url =
00281 octstr_duplicate(e->u.Pom_SessionRequest_Req.dlr_url);
00282 else
00283 wsp_event->u.S_Unit_Push_Req.dlr_url = NULL;
00284 wsp_event->u.S_Unit_Push_Req.dlr_mask = e->u.Pom_SessionRequest_Req.dlr_mask;
00285 if (e->u.Pom_SessionRequest_Req.smsbox_id != NULL)
00286 wsp_event->u.S_Unit_Push_Req.smsbox_id =
00287 octstr_duplicate(e->u.Pom_SessionRequest_Req.smsbox_id);
00288 else
00289 wsp_event->u.S_Unit_Push_Req.smsbox_id = NULL;
00290 wsp_event->u.S_Unit_Push_Req.service_name =
00291 octstr_duplicate(e->u.Pom_SessionRequest_Req.service_name);
00292
00293 wsp_event->u.S_Unit_Push_Req.push_id =
00294 e->u.Pom_SessionRequest_Req.push_id;
00295 wsp_event->u.S_Unit_Push_Req.addr_tuple =
00296 wap_addr_tuple_duplicate(e->u.Pom_SessionRequest_Req.addr_tuple);
00297 wsp_event->u.S_Unit_Push_Req.push_headers =
00298 http_header_duplicate(push_headers);
00299
00300 appid_headers = http_header_find_all(push_headers, "X-WAP-Application-Id");
00301 wsp_event->u.S_Unit_Push_Req.push_body = pack_sia(appid_headers);
00302
00303 debug("wap.push.ota", 0, "OTA: making a connectionless session request for"
00304 " creating a session");
00305
00306 dispatch_to_wsp_unit(wsp_event);
00307 }
00308
00309 static void make_push_request(WAPEvent *e)
00310 {
00311 WAPEvent *wsp_event;
00312 List *push_headers;
00313
00314 gw_assert(e->type == Po_Push_Req);
00315 push_headers = add_push_flag(e);
00316
00317 wsp_event = wap_event_create(S_Push_Req);
00318 wsp_event->u.S_Push_Req.push_headers = push_headers;
00319 if (e->u.Po_Push_Req.push_body != NULL)
00320 wsp_event->u.S_Push_Req.push_body =
00321 octstr_duplicate(e->u.Po_Push_Req.push_body);
00322 else
00323 wsp_event->u.S_Push_Req.push_body = NULL;
00324 wsp_event->u.S_Push_Req.session_id = e->u.Po_Push_Req.session_handle;
00325
00326 dispatch_to_wsp(wsp_event);
00327 }
00328
00329 static void make_confirmed_push_request(WAPEvent *e)
00330 {
00331 WAPEvent *wsp_event;
00332 List *push_headers;
00333
00334 gw_assert(e->type == Po_ConfirmedPush_Req);
00335 push_headers = add_push_flag(e);
00336
00337 wsp_event = wap_event_create(S_ConfirmedPush_Req);
00338 wsp_event->u.S_ConfirmedPush_Req.server_push_id =
00339 e->u.Po_ConfirmedPush_Req.server_push_id;
00340 wsp_event->u.S_ConfirmedPush_Req.push_headers = push_headers;
00341
00342 if (e->u.Po_ConfirmedPush_Req.push_body != NULL)
00343 wsp_event->u.S_ConfirmedPush_Req.push_body =
00344 octstr_duplicate(e->u.Po_ConfirmedPush_Req.push_body);
00345 else
00346 wsp_event->u.S_ConfirmedPush_Req.push_body = NULL;
00347
00348 wsp_event->u.S_ConfirmedPush_Req.session_id =
00349 e->u.Po_ConfirmedPush_Req.session_handle;
00350 debug("wap.push.ota", 0, "OTA: making confirmed push request to wsp");
00351
00352 dispatch_to_wsp(wsp_event);
00353 }
00354
00355 static void make_unit_push_request(WAPEvent *e)
00356 {
00357 WAPEvent *wsp_event;
00358 List *push_headers;
00359 Octstr *smsc_id;
00360 Octstr *dlr_url;
00361 Octstr *smsbox_id;
00362 Octstr *push_body;
00363 Octstr *service_name;
00364
00365 gw_assert(e->type == Po_Unit_Push_Req);
00366 gw_assert(e->u.Po_Unit_Push_Req.addr_tuple);
00367 gw_assert(e->u.Po_Unit_Push_Req.service_name);
00368
00369 smsc_id = octstr_duplicate(e->u.Po_Unit_Push_Req.smsc_id);
00370 dlr_url = octstr_duplicate(e->u.Po_Unit_Push_Req.dlr_url);
00371 smsbox_id = octstr_duplicate(e->u.Po_Unit_Push_Req.smsbox_id);
00372 push_body = octstr_duplicate(e->u.Po_Unit_Push_Req.push_body);
00373 service_name = octstr_duplicate(e->u.Po_Unit_Push_Req.service_name);
00374 push_headers = add_push_flag(e);
00375
00376 wsp_event = wap_event_create(S_Unit_Push_Req);
00377 wsp_event->u.S_Unit_Push_Req.addr_tuple =
00378 wap_addr_tuple_duplicate(e->u.Po_Unit_Push_Req.addr_tuple);
00379 wsp_event->u.S_Unit_Push_Req.push_id = e->u.Po_Unit_Push_Req.push_id;
00380 wsp_event->u.S_Unit_Push_Req.push_headers = push_headers;
00381
00382 wsp_event->u.S_Unit_Push_Req.address_type =
00383 e->u.Po_Unit_Push_Req.address_type;
00384 if (smsc_id != NULL)
00385 wsp_event->u.S_Unit_Push_Req.smsc_id = smsc_id;
00386 else
00387 wsp_event->u.S_Unit_Push_Req.smsc_id = NULL;
00388 if (dlr_url != NULL)
00389 wsp_event->u.S_Unit_Push_Req.dlr_url = dlr_url;
00390 else
00391 wsp_event->u.S_Unit_Push_Req.dlr_url = NULL;
00392 wsp_event->u.S_Unit_Push_Req.dlr_mask = e->u.Po_Unit_Push_Req.dlr_mask;
00393 if (smsbox_id != NULL)
00394 wsp_event->u.S_Unit_Push_Req.smsbox_id = smsbox_id;
00395 else
00396 wsp_event->u.S_Unit_Push_Req.smsbox_id = NULL;
00397 wsp_event->u.S_Unit_Push_Req.service_name = service_name;
00398 if (push_body != NULL)
00399 wsp_event->u.S_Unit_Push_Req.push_body = push_body;
00400 else
00401 wsp_event->u.S_Unit_Push_Req.push_body = NULL;
00402
00403 dispatch_to_wsp_unit(wsp_event);
00404 debug("wap.push.ota", 0, "OTA: made connectionless session service"
00405 " request");
00406 }
00407
00408 static void abort_push(WAPEvent *e)
00409 {
00410 WAPEvent *wsp_event;
00411 long reason;
00412
00413 reason = e->u.Po_PushAbort_Req.reason;
00414 gw_assert(e->type == Po_PushAbort_Req);
00415 reason_assert(reason);
00416
00417 wsp_event = wap_event_create(S_PushAbort_Req);
00418 wsp_event->u.S_PushAbort_Req.push_id = e->u.Po_PushAbort_Req.push_id;
00419 wsp_event->u.S_PushAbort_Req.reason = reason;
00420 wsp_event->u.S_PushAbort_Req.session_handle =
00421 e->u.Po_PushAbort_Req.session_id;
00422
00423 dispatch_to_wsp(wsp_event);
00424 }
00425
00426
00427
00428
00429
00430 static List *add_push_flag(WAPEvent *e)
00431 {
00432 int push_flag,
00433 trusted,
00434 authenticated,
00435 last;
00436
00437 Octstr *buf;
00438 List *headers;
00439
00440 flags_assert(e);
00441
00442 if (e->type == Po_Unit_Push_Req) {
00443 trusted = e->u.Po_Unit_Push_Req.trusted << 1;
00444 authenticated = e->u.Po_Unit_Push_Req.authenticated;
00445 last = e->u.Po_Unit_Push_Req.last << 2;
00446
00447 headers = http_header_duplicate(e->u.Po_Unit_Push_Req.push_headers);
00448
00449 } else if (e->type == Po_Push_Req) {
00450 trusted = e->u.Po_Push_Req.trusted << 1;
00451 authenticated = e->u.Po_Push_Req.authenticated;
00452 last = e->u.Po_Push_Req.last << 2;
00453
00454 headers = http_header_duplicate(e->u.Po_Push_Req.push_headers);
00455
00456 } else if (e->type == Po_ConfirmedPush_Req) {
00457 trusted = e->u.Po_ConfirmedPush_Req.trusted << 1;
00458 authenticated = e->u.Po_ConfirmedPush_Req.authenticated;
00459 last = e->u.Po_ConfirmedPush_Req.last << 2;
00460
00461 headers = http_header_duplicate(
00462 e->u.Po_ConfirmedPush_Req.push_headers);
00463
00464 } else {
00465 debug("wap.ota", 0, "OTA: no push flag when the event is: \n");
00466 wap_event_dump(e);
00467 return NULL;
00468 }
00469
00470 push_flag = 0;
00471 push_flag = push_flag | authenticated | trusted | last;
00472
00473 if (push_flag) {
00474 buf = octstr_format("%d", push_flag);
00475 http_header_add(headers, "Push-Flag", octstr_get_cstr(buf));
00476 octstr_destroy(buf);
00477 }
00478
00479 return headers;
00480 }
00481
00482 static void flags_assert(WAPEvent *e)
00483 {
00484 if (e->type == Po_Unit_Push_Req) {
00485 gw_assert(e->u.Po_Unit_Push_Req.trusted == 0 ||
00486 e->u.Po_Unit_Push_Req.trusted == 1);
00487 gw_assert(e->u.Po_Unit_Push_Req.authenticated == 0 ||
00488 e->u.Po_Unit_Push_Req.authenticated == 1);
00489 gw_assert(e->u.Po_Unit_Push_Req.last == 0 ||
00490 e->u.Po_Unit_Push_Req.last == 1);
00491
00492 } else if (e->type == Po_Push_Req) {
00493 gw_assert(e->u.Po_Push_Req.trusted == 0 ||
00494 e->u.Po_Push_Req.trusted == 1);
00495 gw_assert(e->u.Po_Push_Req.authenticated == 0 ||
00496 e->u.Po_Push_Req.authenticated == 1);
00497 gw_assert(e->u.Po_Push_Req.last == 0 ||
00498 e->u.Po_Push_Req.last == 1);
00499
00500 } else if (e->type == Po_ConfirmedPush_Req) {
00501 gw_assert(e->u.Po_ConfirmedPush_Req.trusted == 0 ||
00502 e->u.Po_ConfirmedPush_Req.trusted == 1);
00503 gw_assert(e->u.Po_ConfirmedPush_Req.authenticated == 0 ||
00504 e->u.Po_ConfirmedPush_Req.authenticated == 1);
00505 gw_assert(e->u.Po_ConfirmedPush_Req.last == 0 ||
00506 e->u.Po_ConfirmedPush_Req.last == 1);
00507 }
00508 }
00509
00510
00511
00512
00513 static void reason_assert(long reason)
00514 {
00515 gw_assert(reason == WSP_ABORT_USERREQ || reason == WSP_ABORT_USERRFS ||
00516 reason == WSP_ABORT_USERPND || reason == WSP_ABORT_USERDCR ||
00517 reason == WSP_ABORT_USERDCU);
00518 }
00519
00520
00521
00522
00523
00524
00525
00526 static void check_session_request_headers(List *headers)
00527 {
00528 if (!http_type_accepted(headers, "application/wnd.wap.sia"))
00529 http_header_add(headers, "Content-Type", "application/vnd.wap.sia");
00530 }
00531
00532
00533
00534
00535
00536 static Octstr *pack_sia(List *headers)
00537 {
00538 Octstr *sia_content;
00539 WSP_PDU *pdu;
00540
00541 pdu = wsp_pdu_create(sia);
00542
00543 pdu->u.sia.version = CURRENT_VERSION;
00544 pdu->u.sia.application_id_list = pack_appid_list(headers);
00545 pdu->u.sia.contactpoints = pack_server_address();
00546 sia_content = wsp_pdu_pack(pdu);
00547
00548 wsp_pdu_destroy(pdu);
00549 http_destroy_headers(headers);
00550
00551 return sia_content;
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 static Octstr *pack_appid_list(List *headers)
00564 {
00565 Octstr *appid_os,
00566 *header_name,
00567 *header_value;
00568 long i;
00569 size_t len;
00570
00571 i = 0;
00572 appid_os = octstr_create("");
00573 len = (size_t) gwlist_len(headers);
00574
00575 gw_assert(len);
00576
00577 while (i < len) {
00578 http_header_get(headers, i, &header_name, &header_value);
00579 gw_assert(octstr_compare(header_name,
00580 octstr_imm("X-WAP-Application-Id")) == 0);
00581 octstr_format_append(appid_os, "%S", header_value);
00582 octstr_destroy(header_name);
00583 octstr_destroy(header_value);
00584 ++i;
00585 }
00586
00587 return appid_os;
00588 }
00589
00590
00591
00592
00593
00594 static Octstr *pack_server_address(void)
00595 {
00596 Octstr *address,
00597 *ip_address;
00598 unsigned char address_len;
00599 long port;
00600 int bearer_type;
00601
00602 bearer_type = GSM_CSD_IPV4;
00603 port = CONNECTED_PORT;
00604
00605 mutex_lock(bearerbox->mutex);
00606 ip_address = octstr_duplicate(bearerbox->address);
00607 address_len = octstr_len(bearerbox->address);
00608 mutex_unlock(bearerbox->mutex);
00609
00610 address = octstr_create("");
00611 octstr_append_char(address, address_len);
00612 octstr_set_bits(address, 0, 1, 1);
00613 octstr_set_bits(address, 1, 1, 1);
00614 octstr_append_char(address, bearer_type);
00615 octstr_append_decimal(address, port);
00616 octstr_append(address, ip_address);
00617 octstr_destroy(ip_address);
00618
00619 return address;
00620 }
00621
00622
00623
00624
00625
00626 static Octstr *name(Octstr *in)
00627 {
00628 if (octstr_compare(in, octstr_imm("localhost")) != 0)
00629 return octstr_duplicate(in);
00630 else
00631 return octstr_duplicate(get_official_ip());
00632 }
00633
00634 static BearerboxAddress *bearerbox_address_create(void)
00635 {
00636 BearerboxAddress *ba;
00637
00638 ba = gw_malloc(sizeof(BearerboxAddress));
00639 ba->mutex = mutex_create();
00640 ba->address = NULL;
00641
00642 return ba;
00643 }
00644
00645 static void bearerbox_address_destroy(BearerboxAddress *ba)
00646 {
00647 if (ba == NULL)
00648 return;
00649
00650 octstr_destroy(ba->address);
00651 mutex_destroy(ba->mutex);
00652 gw_free(ba);
00653 }
00654
00655
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.