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

wap_push_ota.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * Wap_push_ota.c: implementation of push related requests of OTA protocol
00059  *
00060  * This module implements requirement primitives of WAP-189-PushOTA-20000217-a
00061  * (hereafter called ota).
00062  * In addition, WAP-203-WSP-20000504-a (wsp) is referred.
00063  *
00064  * This module forwards push  requests made by the wap_push_ppg module to 
00065  * connected or connectionless session services.
00066  * Indications (for confirmed push, push abort and disconnect, e.g., in the 
00067  * case of unability to create a session) of OTA protocol are done for wap_
00068  * push_ppg module by a module common with pull, wap-appl. 
00069  *
00070  * Note that push header encoding and decoding are divided into two parts:
00071  * first decoding and encoding numeric values and then packing these values
00072  * into WSP format and unpacking them from WSP format. This module contains
00073  * decoding part.
00074  *
00075  * By Aarno Syvänen for Wapit Ltd and Global Networks Inc.
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  * Internal data structures
00089  */ 
00090 
00091 /*
00092  * Give the status of the push ota module:
00093  *
00094  *  limbo
00095  *      not running at all
00096  *  running
00097  *      operating normally
00098  *  terminating
00099  *      waiting for operations to terminate, returning to limbo
00100  */
00101 static enum {limbo, running, terminating} run_status = limbo;
00102 
00103 /*
00104  * Bearerbox address for the phone (it needs to know who it is talking with)
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  * Prototypes of internal functions
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  * Add push flag into push headers. Push flag is defined in PushOTA, p. 17-18.
00134  */
00135 static List *add_push_flag(WAPEvent *e);
00136 
00137 /*
00138  * When server is requesting a session with a client, content type and applic-
00139  * ation headers must be present (this behaviour is defined in PushOTA, p. 14).
00140  * We check headers for them and add them if they are not already present.
00141  */
00142 static void check_session_request_headers(List *headers);
00143 
00144 /*
00145  * Contact points and application ids in the push initiator are packed into a
00146  * specific structure, being like WSP PDUs.
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  * Returns bearerbox ip address. Resolve it, if the address is localhost.
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  * EXTERNAL FUNCTIONS
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  * Sets bearerbox address, used for push contact point. Resolve address local-
00201  * host before assignment.
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  * INTERNAL FUNCTIONS
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  * Add push flag into push headers. Push flag is defined in ota, p. 17-18.
00428  * If there is no flags set, no Push-Flag header is added.
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  * Accepted reasons are defined in ota 6.3.3.
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  * When server is requesting a session with a client, content type and applic-
00522  * ation headers must be present (this behaviour is defined in ota, p. 14).
00523  * We check headers for them and add them if they are not already present. 
00524  * X-WAP-Application-Id has been added by ppg module.
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  * Pack contact points and application id list into sia content type. It is 
00534  * defined in ota, p. 18. 
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  * Input: List of headers containing only X-Wap-Application-Id headers, values
00556  * being numeric application id codes. (Ppg module does coding of the header 
00557  * value part of the X-WAP-Application-Id header).
00558  * Output: Octstr containing them in a byte list (one id per byte). 
00559  *
00560  * Returns: Octstr containing headers, if succesfull, otherwise an empty 
00561  * octstr.
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  * NB: This data includes bearer information. We use IPv4 values. Address Type
00592  * is defined in wsp, table 16, p. 65
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); /* bearer type included */
00613     octstr_set_bits(address, 1, 1, 1); /* port number included */
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  * Returns bearerbox ip address. Resolve it, if the address is localhost. Do 
00624  * not panic here. Even if we cannot do push, we still can do pull.
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.