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

wsp_unit.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  * wsp_unit.c - Implement WSP Connectionless mode
00059  *
00060  * Lars Wirzenius
00061  */
00062 
00063 
00064 #include <string.h>
00065 
00066 #include "gwlib/gwlib.h"
00067 #include "wsp.h"
00068 #include "wsp_pdu.h"
00069 #include "wsp_headers.h"
00070 #include "wap_events.h"
00071 #include "wsp_strings.h"
00072 #include "wap.h"
00073 
00074 
00075 /*
00076  * Give the status the module:
00077  *
00078  *  limbo
00079  *      not running at all
00080  *  running
00081  *      operating normally
00082  *  terminating
00083  *      waiting for operations to terminate, returning to limbo
00084  */
00085 static enum { limbo, running, terminating } run_status = limbo;
00086 
00087 static wap_dispatch_func_t *dispatch_to_wdp;
00088 static wap_dispatch_func_t *dispatch_to_appl;
00089 
00090 static List *queue = NULL;
00091 
00092 
00093 static void main_thread(void *);
00094 static WAPEvent *pack_into_result_datagram(WAPEvent *event);
00095 static WAPEvent *pack_into_push_datagram(WAPEvent *event);
00096 
00097 /***********************************************************************
00098  * Public functions
00099  */
00100 
00101 
00102 void wsp_unit_init(wap_dispatch_func_t *datagram_dispatch,
00103                    wap_dispatch_func_t *application_dispatch) {
00104     queue = gwlist_create();
00105     gwlist_add_producer(queue);
00106     dispatch_to_wdp = datagram_dispatch;
00107     dispatch_to_appl = application_dispatch;
00108         wsp_strings_init();
00109     run_status = running;
00110     gwthread_create(main_thread, NULL);
00111 }
00112 
00113 
00114 void wsp_unit_shutdown(void) {
00115     gw_assert(run_status == running);
00116     run_status = terminating;
00117     gwlist_remove_producer(queue);
00118     gwthread_join_every(main_thread);
00119     gwlist_destroy(queue, wap_event_destroy_item);
00120         wsp_strings_shutdown();
00121 }
00122 
00123 
00124 void wsp_unit_dispatch_event(WAPEvent *event) {
00125     wap_event_assert(event);
00126     gwlist_produce(queue, event);
00127 }
00128 
00129 
00130 static WAPEvent *unpack_datagram(WAPEvent *datagram) {
00131     WAPEvent *event;
00132     Octstr *os;
00133     WSP_PDU *pdu;
00134     long tid_byte;
00135     int method;
00136     Octstr *method_name;
00137 
00138     gw_assert(datagram->type == T_DUnitdata_Ind);
00139     
00140     os = NULL;
00141     pdu = NULL;
00142     event = NULL;
00143 
00144     os = octstr_duplicate(datagram->u.T_DUnitdata_Ind.user_data);
00145     if (os && octstr_len(os) == 0) {
00146         warning(0, "WSP UNIT: Empty datagram.");
00147         goto error;
00148     }
00149     
00150     tid_byte = octstr_get_char(os, 0);
00151     octstr_delete(os, 0, 1);
00152     
00153     pdu = wsp_pdu_unpack(os);
00154     if (pdu == NULL)
00155         goto error;
00156     
00157     if (pdu->type != Get && pdu->type != Post) {
00158         warning(0, "WSP UNIT: Unsupported PDU type %d", pdu->type);
00159         goto error;
00160     }
00161         
00162     event = wap_event_create(S_Unit_MethodInvoke_Ind);
00163     event->u.S_Unit_MethodInvoke_Ind.addr_tuple = wap_addr_tuple_duplicate(
00164                 datagram->u.T_DUnitdata_Ind.addr_tuple);
00165     event->u.S_Unit_MethodInvoke_Ind.transaction_id = tid_byte;
00166         
00167     switch (pdu->type) {
00168     case Get:
00169         debug("wap.wsp", 0, "Connectionless Get request received.");
00170         method = GET_METHODS + pdu->u.Get.subtype;
00171         event->u.S_Unit_MethodInvoke_Ind.request_uri = 
00172             octstr_duplicate(pdu->u.Get.uri);
00173         event->u.S_Unit_MethodInvoke_Ind.request_headers = 
00174             wsp_headers_unpack(pdu->u.Get.headers, 0);
00175         event->u.S_Unit_MethodInvoke_Ind.request_body = NULL;
00176         break;
00177 
00178     case Post:
00179         debug("wap.wsp", 0, "Connectionless Post request received.");
00180                 method = POST_METHODS + pdu->u.Post.subtype;
00181         event->u.S_Unit_MethodInvoke_Ind.request_uri = 
00182             octstr_duplicate(pdu->u.Post.uri);
00183         event->u.S_Unit_MethodInvoke_Ind.request_headers = 
00184             wsp_headers_unpack(pdu->u.Post.headers, 1);
00185         event->u.S_Unit_MethodInvoke_Ind.request_body = 
00186             octstr_duplicate(pdu->u.Post.data);
00187         break;
00188 
00189     default:
00190         warning(0, "WSP UNIT: Unsupported PDU type %d", pdu->type);
00191         goto error;
00192     }
00193 
00194     method_name = wsp_method_to_string(method);
00195     if (method_name == NULL)
00196         method_name = octstr_format("UNKNOWN%02X", method);
00197     event->u.S_Unit_MethodInvoke_Ind.method = method_name;
00198 
00199     octstr_destroy(os);
00200     wsp_pdu_destroy(pdu);
00201     return event;
00202 
00203 error:
00204     octstr_destroy(os);
00205     wsp_pdu_destroy(pdu);
00206     wap_event_destroy(event);
00207     return NULL;
00208 }
00209 
00210 
00211 /***********************************************************************
00212  * Local functions
00213  */
00214 
00215 static void main_thread(void *arg) 
00216 {
00217     WAPEvent *e;
00218     WAPEvent *newevent;
00219     
00220     while (run_status == running && (e = gwlist_consume(queue)) != NULL) {
00221         debug("wap.wsp.unit", 0, "WSP (UNIT): event arrived");
00222         wap_event_assert(e);
00223         switch (e->type) {
00224             case T_DUnitdata_Ind:
00225                 newevent = unpack_datagram(e);
00226                 if (newevent != NULL)
00227                     dispatch_to_appl(newevent);
00228                 break;
00229 
00230             case S_Unit_MethodResult_Req:
00231                 newevent = pack_into_result_datagram(e);
00232                 if (newevent != NULL)
00233                     dispatch_to_wdp(newevent);
00234                 break;
00235 
00236             case S_Unit_Push_Req:
00237                 newevent = pack_into_push_datagram(e);
00238                 if (newevent != NULL) 
00239                     dispatch_to_wdp(newevent);
00240                 debug("wsp.unit", 0, "WSP (UNIT): delivering to wdp");
00241                 break;
00242     
00243             default:
00244                 warning(0, "WSP UNIT: Unknown event type %d", e->type);
00245                 break;
00246         }
00247         wap_event_destroy(e);
00248     }
00249 }
00250 
00251 
00252 /*
00253  * We do not set TUnitData.ind's SMS-specific fields here, because we do not
00254  * support sending results to the phone over SMS. Wsp, chapter 8.4.1 states
00255  * that "that each peer entity is always associated with an encoding version.".
00256  * So we add Encoding-Version when we are sending something to the client.
00257  * (This includes push, which is not directly mentioned in chapter 8.4.2.70). 
00258  */
00259 static WAPEvent *pack_into_result_datagram(WAPEvent *event) {
00260     WAPEvent *datagram;
00261     struct S_Unit_MethodResult_Req *p;
00262     WSP_PDU *pdu;
00263     Octstr *ospdu;
00264     unsigned char tid;
00265     
00266     gw_assert(event->type == S_Unit_MethodResult_Req);
00267     p = &event->u.S_Unit_MethodResult_Req;
00268 
00269     http_header_add(p->response_headers, "Encoding-Version", "1.3");
00270 
00271     pdu = wsp_pdu_create(Reply);
00272     pdu->u.Reply.status = wsp_convert_http_status_to_wsp_status(p->status);
00273     pdu->u.Reply.headers = wsp_headers_pack(p->response_headers, 1, WSP_1_3);
00274     pdu->u.Reply.data = octstr_duplicate(p->response_body);
00275     ospdu = wsp_pdu_pack(pdu);
00276     wsp_pdu_destroy(pdu);
00277     if (ospdu == NULL)
00278         return NULL;
00279 
00280     tid = p->transaction_id;
00281     octstr_insert_data(ospdu, 0, (char *)&tid, 1);
00282 
00283     datagram = wap_event_create(T_DUnitdata_Req);
00284     datagram->u.T_DUnitdata_Req.addr_tuple =
00285         wap_addr_tuple_duplicate(p->addr_tuple);
00286     datagram->u.T_DUnitdata_Req.user_data = ospdu;
00287 
00288     return datagram;
00289 }
00290 
00291 /*
00292  * According to WSP table 12, p. 63, push id and transaction id are stored 
00293  * into same field. T-UnitData.ind is different for IP and SMS bearer.
00294  */
00295 static WAPEvent *pack_into_push_datagram(WAPEvent *event) {
00296         WAPEvent *datagram;
00297         WSP_PDU *pdu;
00298         Octstr *ospdu;
00299     unsigned char push_id;
00300 
00301         gw_assert(event->type == S_Unit_Push_Req);
00302         debug("wap.wsp.unit", 0, "WSP_UNIT: Connectionless push accepted");
00303 
00304         http_header_add(event->u.S_Unit_Push_Req.push_headers, 
00305                         "Encoding-Version", "1.3");
00306 
00307         pdu = wsp_pdu_create(Push);
00308     pdu->u.Push.headers = wsp_headers_pack(
00309             event->u.S_Unit_Push_Req.push_headers, 1, WSP_1_3);
00310     pdu->u.Push.data = octstr_duplicate(
00311             event->u.S_Unit_Push_Req.push_body);
00312         ospdu = wsp_pdu_pack(pdu);
00313     wsp_pdu_destroy(pdu);
00314     if (ospdu == NULL)
00315         return NULL;
00316 
00317         push_id = event->u.S_Unit_Push_Req.push_id;
00318     octstr_insert_data(ospdu, 0, (char *)&push_id, 1);
00319 
00320         datagram = wap_event_create(T_DUnitdata_Req);
00321 
00322         datagram->u.T_DUnitdata_Req.addr_tuple =
00323         wap_addr_tuple_duplicate(event->u.S_Unit_Push_Req.addr_tuple);
00324         datagram->u.T_DUnitdata_Req.address_type = 
00325         event->u.S_Unit_Push_Req.address_type;
00326         if (event->u.S_Unit_Push_Req.smsc_id != NULL)
00327             datagram->u.T_DUnitdata_Req.smsc_id =
00328                 octstr_duplicate(event->u.S_Unit_Push_Req.smsc_id);
00329         else
00330             datagram->u.T_DUnitdata_Req.smsc_id = NULL;
00331         if (event->u.S_Unit_Push_Req.dlr_url != NULL)
00332             datagram->u.T_DUnitdata_Req.dlr_url =
00333                 octstr_duplicate(event->u.S_Unit_Push_Req.dlr_url);
00334         else
00335             datagram->u.T_DUnitdata_Req.dlr_url = NULL;
00336         datagram->u.T_DUnitdata_Req.dlr_mask = event->u.S_Unit_Push_Req.dlr_mask;
00337         if (event->u.S_Unit_Push_Req.smsbox_id != NULL)
00338             datagram->u.T_DUnitdata_Req.smsbox_id =
00339                 octstr_duplicate(event->u.S_Unit_Push_Req.smsbox_id);
00340         else       
00341             datagram->u.T_DUnitdata_Req.smsbox_id = NULL;
00342         datagram->u.T_DUnitdata_Req.service_name =
00343             octstr_duplicate(event->u.S_Unit_Push_Req.service_name);
00344 
00345     datagram->u.T_DUnitdata_Req.user_data = ospdu;
00346         
00347         return datagram;
00348 }
00349 
00350 
00351 
00352 
00353 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.