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 #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
00077
00078
00079
00080
00081
00082
00083
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
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
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
00254
00255
00256
00257
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
00293
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.