80 #define STATE_NAME(name) name, 81 #define ROW(state, event, condition, action, next_state) 84 #define STATE_NAME(name) name, 85 #define ROW(state, event, condition, action, next_state) 88 #define STATE_NAME(name) name, 89 #define ROW(state, event, condition, action, next_state) 162 static void send_abort(
long reason,
long handle);
166 List *client_headers);
219 debug(
"wap.wsp", 0,
"WSP: %ld session machines left.",
250 warning(0,
"WSP: Broken PDU ignored.");
281 switch (event->
type) {
284 event->
u.TR_Invoke_Ind.addr_tuple);
289 event->
u.TR_Invoke_Cnf.addr_tuple);
294 event->
u.TR_Result_Cnf.addr_tuple);
299 event->
u.TR_Abort_Ind.addr_tuple);
303 session_id =
event->u.S_Connect_Res.session_id;
307 session_id =
event->u.S_Resume_Res.session_id;
310 case Disconnect_Event:
311 session_id =
event->u.Disconnect_Event.session_handle;
315 session_id =
event->u.Suspend_Event.session_handle;
318 case S_MethodInvoke_Res:
319 session_id =
event->u.S_MethodInvoke_Res.session_id;
322 case S_MethodResult_Req:
323 session_id =
event->u.S_MethodResult_Req.session_id;
326 case S_ConfirmedPush_Req:
327 session_id =
event->u.S_ConfirmedPush_Req.session_id;
331 session_id =
event->u.S_Push_Req.session_id;
335 error(0,
"WSP: Cannot find machine for %s event",
339 gw_assert(tuple != NULL || session_id != -1);
347 if (event->
type == TR_Invoke_Ind &&
348 event->
u.TR_Invoke_Ind.tcl == 2 &&
349 pdu->
type == Connect) {
356 sm->connect_handle =
event->u.TR_Invoke_Ind.handle;
358 }
else if (event->
type == TR_Invoke_Ind &&
359 event->
u.TR_Invoke_Ind.tcl == 2 &&
360 pdu->
type == Resume) {
363 session_id = pdu->
u.Resume.sessionid;
369 event->
u.TR_Invoke_Ind.handle);
375 }
else if (event->
type == TR_Invoke_Ind) {
378 if (sm == NULL && (event->
u.TR_Invoke_Ind.tcl == 1 ||
379 event->
u.TR_Invoke_Ind.tcl == 2)) {
381 event->
u.TR_Invoke_Ind.handle);
386 if (session_id != -1) {
398 error(0,
"WSP: Cannot find session machine for event.");
410 debug(
"wap.wsp", 0,
"WSP: machine %p, state %s, event %s",
415 #define STATE_NAME(name) 416 #define ROW(state_name, event, condition, action, next_state) \ 419 e = ¤t_event->u.event; \ 420 if (sm->state == state_name && \ 421 current_event->type == event && \ 424 sm->state = next_state; \ 425 debug("wap.wsp", 0, "WSP %ld: New state %s", \ 426 sm->session_id, #next_state); \ 437 if (sm->state == NULL_SESSION)
446 if (event->
type == TR_Invoke_Ind &&
447 (event->
u.TR_Invoke_Ind.tcl == 1 ||
448 event->
u.TR_Invoke_Ind.tcl == 2)) {
449 warning(0,
"WSP: Can't handle TR-Invoke.ind, aborting transaction.");
450 debug(
"wap.wsp", 0,
"WSP: The unhandled event:");
453 event->
u.TR_Invoke_Ind.handle);
455 }
else if (event->
type == TR_Invoke_Ind) {
456 warning(0,
"WSP: Can't handle TR-Invoke.ind, ignoring.");
457 debug(
"wap.wsp", 0,
"WSP: The ignored event:");
461 error(0,
"WSP: Can't handle event. Aborting session.");
462 debug(
"wap.wsp", 0,
"WSP: The unhandled event:");
470 if (event->
type == TR_Result_Cnf) {
472 event->
u.TR_Result_Cnf.handle);
487 debug(
"wap.wsp", 0,
"WSP: Created WSPMachine %p", (
void *) p);
489 #define INTEGER(name) p->name = 0; 490 #define OCTSTR(name) p->name = NULL; 491 #define HTTPHEADERS(name) p->name = NULL; 492 #define ADDRTUPLE(name) p->name = NULL; 493 #define MACHINESLIST(name) p->name = gwlist_create(); 494 #define CAPABILITIES(name) p->name = NULL; 495 #define COOKIES(name) p->name = gwlist_create(); 496 #define REFERER(name) p->name = NULL; 497 #define MACHINE(fields) fields 500 p->state = NULL_SESSION;
504 p->client_SDU_size = 1400;
519 warning(0,
"Destroying WSP session with %ld active methods\n",
528 warning(0,
"Destroying WSP session with %ld active pushes\n",
539 debug(
"wap.wsp", 0,
"Destroying WSPMachine %p", pp);
542 #define INTEGER(name) p->name = 0; 543 #define OCTSTR(name) octstr_destroy(p->name); 544 #define HTTPHEADERS(name) http_destroy_headers(p->name); 545 #define ADDRTUPLE(name) wap_addr_tuple_destroy(p->name); 546 #define MACHINESLIST(name) destroy_##name(p->name); 547 #define CAPABILITIES(name) wsp_cap_destroy_list(p->name); 548 #define COOKIES(name) cookies_destroy(p->name); 549 #define REFERER(name) octstr_destroy(p->name); 550 #define MACHINE(fields) fields 568 warning(0,
"No method machine for event.");
573 debug(
"wap.wsp", 0,
"WSP: method %ld, state %s, event %s",
577 gw_assert(sm->session_id == msm->session_id);
579 #define STATE_NAME(name) 580 #define ROW(state_name, event, condition, action, next_state) \ 583 e = ¤t_event->u.event; \ 584 if (msm->state == state_name && \ 585 current_event->type == event && \ 588 msm->state = next_state; \ 589 debug("wap.wsp", 0, "WSP %ld/%ld: New method state %s", \ 590 msm->session_id, msm->transaction_id, #next_state); \ 599 if (msm->state == NULL_METHOD) {
610 msm = gw_malloc(
sizeof(*msm));
612 #define INTEGER(name) msm->name = 0; 613 #define ADDRTUPLE(name) msm->name = NULL; 614 #define EVENT(name) msm->name = NULL; 615 #define MACHINE(fields) fields 618 msm->transaction_id = wtp_handle;
619 msm->state = NULL_METHOD;
621 msm->session_id = sm->session_id;
638 debug(
"wap.wsp", 0,
"Destroying WSPMethodMachine %ld",
639 msm->transaction_id);
641 #define INTEGER(name) 642 #define ADDRTUPLE(name) wap_addr_tuple_destroy(msm->name); 643 #define EVENT(name) wap_event_destroy(msm->name); 644 #define MACHINE(fields) fields 654 warning(0,
"No push machine for event.");
659 debug(
"wap.wsp", 0,
"WSP(tid/pid): push %ld/%ld, state %s, event %s",
660 pm->transaction_id, pm->server_push_id,
state_name(pm->state),
662 gw_assert(sm->session_id == pm->session_id);
664 #define STATE_NAME(name) 665 #define ROW(state_name, event, condition, action, next_state) \ 667 if (pm->state == state_name && \ 668 current_event->type == event && \ 671 pm->state = next_state; \ 672 debug("wap.wsp", 0, "WSP %ld/%ld: New push state %s", \ 673 pm->session_id, pm->transaction_id, #next_state); \ 681 if (pm->state == SERVER_PUSH_NULL_STATE) {
694 #define INTEGER(name) m->name = 0; 695 #define ADDRTUPLE(name) m->name = NULL; 696 #define HTTPHEADER(name) m->name = http_create_empty_headers(); 697 #define MACHINE(fields) fields 700 m->server_push_id = pid;
701 m->transaction_id = pid;
702 m->state = SERVER_PUSH_NULL_STATE;
704 m->session_id = sm->session_id;
718 debug(
"wap.wsp", 0,
"Destroying WSPPushMachine %ld",
720 #define INTEGER(name) 721 #define ADDRTUPLE(name) wap_addr_tuple_destroy(m->name); 722 #define HTTPHEADER(name) http_destroy_headers(m->name); 723 #define MACHINE(fields) fields 731 #define STATE_NAME(name) case name: return #name; 732 #define ROW(state, event, cond, stmt, next_state) 735 #define STATE_NAME(name) case name: return #name; 736 #define ROW(state, event, cond, stmt, next_state) 739 #define STATE_NAME(name) case name: return #name; 740 #define ROW(state, event, cond, stmt, next_state) 744 return "unknown wsp state";
764 if (cap->
name != NULL)
772 if (cap->
data != NULL &&
776 m->client_SDU_size = ui;
781 if (cap->
data != NULL &&
796 warning(0,
"WSP: Application layer tried to " 797 "negotiate protocol options.");
817 error(0,
"WSP: Found illegal value in capabilities reply.");
835 if ((ui >= 256 && ui < LONG_MAX) || ui == 0) {
836 m->client_SDU_size = ui;
914 for (i = 0; i < len; i++) {
934 return (cap->
data != NULL &&
1012 Octstr *encoding_version;
1039 List *reply_headers;
1043 pdu->
u.ConnectReply.sessionid = m->session_id;
1050 pdu->
u.ConnectReply.headers =
1070 if (headers == NULL) {
1094 if (e->
u.S_ConfirmedPush_Req.push_headers == NULL) {
1099 pdu->
u.ConfirmedPush.headers =
1102 if (e->
u.S_ConfirmedPush_Req.push_body == NULL)
1105 pdu->
u.ConfirmedPush.data =
1120 if (e->
u.S_Push_Req.push_headers == NULL) {
1125 pdu->
u.Push.headers =
1128 if (e->
u.S_Push_Req.push_body == NULL)
1152 return wsp->session_id == *idp;
1160 return msm->transaction_id == *idp;
1167 return m->transaction_id == *idp;
1195 if (old_sessions == NULL)
1198 for (i = 0; i <
gwlist_len(old_sessions); i++) {
1215 if (sm->http_headers == NULL)
1228 wtp_event->
u.TR_Abort_Req.abort_type = 0x01;
1229 wtp_event->
u.TR_Abort_Req.abort_reason = reason;
1230 wtp_event->
u.TR_Abort_Req.handle = handle;
1259 wtp_event->
u.TR_Invoke_Req.addr_tuple =
1267 wtp_event->
u.TR_Invoke_Req.tcl =
class;
1268 if (e->
type == S_ConfirmedPush_Req)
1269 wtp_event->
u.TR_Invoke_Req.handle =
1270 e->
u.S_ConfirmedPush_Req.server_push_id;
1281 new_event->
u.S_Disconnect_Ind.reason_code = reason;
1282 new_event->
u.S_Disconnect_Ind.redirect_security = 0;
1283 new_event->
u.S_Disconnect_Ind.redirect_addresses = 0;
1284 new_event->
u.S_Disconnect_Ind.error_headers = NULL;
1285 new_event->
u.S_Disconnect_Ind.error_body = NULL;
1286 new_event->
u.S_Disconnect_Ind.session_handle = sm->session_id;
1295 new_event->
u.S_Suspend_Ind.reason = reason;
1296 new_event->
u.S_Suspend_Ind.session_id = sm->session_id;
1308 new_event->
u.S_Resume_Ind.session_id = sm->session_id;
1317 ota_event->
u.S_PushAbort_Ind.push_id = spm->server_push_id;
1318 ota_event->
u.S_PushAbort_Ind.reason = reason;
1319 ota_event->
u.S_PushAbort_Ind.session_id = spm->session_id;
1328 ota_event->
u.S_ConfirmedPush_Cnf.server_push_id = m->server_push_id;
1329 ota_event->
u.S_ConfirmedPush_Cnf.session_id = m->session_id;
1341 wtp_event->
u.TR_Abort_Req.abort_type = 0x00;
1343 wtp_event->
u.TR_Abort_Req.abort_type = 0x01;
1345 wtp_event->
u.TR_Abort_Req.abort_reason = reason;
1346 wtp_event->
u.TR_Abort_Req.handle = msm->transaction_id;
1357 new_event->
u.S_MethodAbort_Ind.transaction_id = msm->transaction_id;
1358 new_event->
u.S_MethodAbort_Ind.reason = reason;
1359 new_event->
u.S_MethodAbort_Ind.session_handle = msm->session_id;
1367 return msm->state == HOLDING;
1378 if (holding == NULL)
1386 for (i = 0; i < len; i++) {
1401 ab->
u.Abort_Event.reason = reason;
1406 for (i = len - 1; i >= 0; i--) {
1422 ab->
u.Abort_Event.reason = reason;
1425 for (i = len - 1; i >= 0; i--) {
1447 if (*
id == wsp->session_id)
return 1;
long wsp_convert_http_status_to_wsp_status(long http_status)
void error(int err, const char *fmt,...)
int wsp_cap_get_push_mor(List *caps_list, unsigned long *mor)
void wsp_session_shutdown(void)
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
static void release_holding_methods(WSPMachine *sm)
static int find_by_session_id(void *session, void *idp)
void wsp_cap_destroy_list(List *caps_list)
void http_header_add(List *headers, char *name, char *contents)
gw_assert(wtls_machine->packet_to_send !=NULL)
int wsp_cap_get_server_sdu(List *caps_list, unsigned long *sdu)
void counter_destroy(Counter *counter)
static void handle_push_event(WSPMachine *session, WSPPushMachine *machine, WAPEvent *e)
void gwlist_append(List *list, void *item)
static void indicate_resume(WSPMachine *sm, WAPAddrTuple *tuple, List *client_headers)
static void indicate_disconnect(WSPMachine *sm, long reason)
static void abort_methods(WSPMachine *sm, long reason)
static void handle_session_event(WSPMachine *machine, WAPEvent *event, WSP_PDU *pdu)
static unsigned long next_wsp_session_id(void)
void gwlist_produce(List *list, void *item)
long gwlist_len(List *list)
static WSP_PDU * make_confirmedpush_pdu(WAPEvent *e)
void * gwlist_get(List *list, long pos)
void octstr_set_bits(Octstr *ostr, long bitpos, int numbits, unsigned long value)
void http_header_combine(List *old_headers, List *new_headers)
static void sanitize_capabilities(List *caps, WSPMachine *m)
void octstr_append_char(Octstr *ostr, int ch)
Capability * wsp_cap_create(int id, Octstr *name, Octstr *data)
static void strip_default_capabilities(List *caps, List *req)
static void push_machine_destroy(void *p)
void wsp_cap_dump(Capability *cap)
static WSPPushMachine * push_machine_create(WSPMachine *session, long id)
Octstr * wsp_pdu_pack(WSP_PDU *pdu)
WAPAddrTuple * addr_tuple
static WSP_PDU * make_push_pdu(WAPEvent *e)
static void abort_pushes(WSPMachine *sm, long reason)
List * wsp_cap_duplicate_list(List *caps_list)
static WSPMachine * machine_create(void)
static void confirm_push(WSPPushMachine *machine)
static int is_default_cap(Capability *cap)
#define octstr_get_cstr(ostr)
static int find_by_method_id(void *wspm_ptr, void *id_ptr)
void wap_event_dump(WAPEvent *event)
void gwthread_join_every(gwthread_func_t *func)
unsigned long counter_increase(Counter *counter)
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
void wsp_session_init(wap_dispatch_func_t *responder_dispatch, wap_dispatch_func_t *initiator_dispatch, wap_dispatch_func_t *application_dispatch, wap_dispatch_func_t *push_ota_dispatch)
static List * session_machines
List * gwlist_search_all(List *list, void *pattern, int(*cmp)(void *, void *))
static WSPPushMachine * find_push_machine(WSPMachine *m, long id)
void http_destroy_headers(List *headers)
WSP_PDU * wsp_pdu_create(int type)
int wsp_cap_get_client_sdu(List *caps_list, unsigned long *sdu)
static void method_abort(WSPMethodMachine *msm, long reason)
static int same_client(void *sm1, void *sm2)
static void send_invoke(WSPMachine *session, WSP_PDU *pdu, WAPEvent *e, long class)
Octstr * octstr_imm(const char *cstr)
Counter * counter_create(void)
static WSPMachine * find_session_machine(WAPEvent *event, WSP_PDU *pdu)
static Octstr * make_resume_reply_pdu(WSPMachine *m, List *headers)
void gwlist_delete(List *list, long pos, long count)
void wap_event_assert(WAPEvent *event)
void gwlist_remove_producer(List *list)
static void destroy_pushmachines(List *machines)
List * http_create_empty_headers(void)
void wap_event_destroy_item(void *event)
static WSPMethodMachine * find_method_machine(WSPMachine *, long id)
static void machine_destroy(void *p)
#define octstr_duplicate(ostr)
const char * wap_event_name(WAPEventName type)
int wsp_cap_get_method_mor(List *caps_list, unsigned long *mor)
static void main_thread(void *)
long gwlist_delete_equal(List *list, void *item)
static wap_dispatch_func_t * dispatch_to_appl
#define wap_event_create(type)
int wsp_cap_count(List *caps_list, int id, Octstr *name)
void warning(int err, const char *fmt,...)
static void refuse_unreplied_capabilities(List *caps, List *req)
static Octstr * make_connectreply_pdu(WSPMachine *m)
void octstr_destroy(Octstr *ostr)
void wap_addr_tuple_destroy(WAPAddrTuple *tuple)
static void destroy_methodmachines(List *machines)
#define gwthread_create(func, arg)
#define octstr_create(cstr)
static int find_by_push_id(void *m_ptr, void *id_ptr)
static WSPMethodMachine * method_machine_create(WSPMachine *, long)
void wsp_pdu_destroy(WSP_PDU *pdu)
static enum @91 run_status
static int wsp_encoding_string_to_version(Octstr *enc)
static void reply_known_capabilities(List *caps, List *req, WSPMachine *m)
void gwlist_insert(List *list, long pos, void *item)
static void indicate_method_abort(WSPMethodMachine *msm, long reason)
static void indicate_suspend(WSPMachine *sm, long reason)
static int id_belongs_to_session(void *, void *)
static void handle_method_event(WSPMachine *session, WSPMethodMachine *machine, WAPEvent *event, WSP_PDU *pdu)
static int transaction_belongs_to_session(void *session, void *tuple)
long octstr_len(const Octstr *ostr)
int wap_addr_tuple_same(WAPAddrTuple *a, WAPAddrTuple *b)
static Octstr * wsp_encoding_version_to_string(int version)
void octstr_append_uintvar(Octstr *ostr, unsigned long value)
WSPMachine * find_session_machine_by_id(int id)
static List * unpack_new_headers(WSPMachine *sm, Octstr *hdrs)
void wsp_strings_shutdown(void)
void * gwlist_consume(List *list)
void wsp_strings_init(void)
static wap_dispatch_func_t * dispatch_to_wtp_resp
void debug(const char *place, int err, const char *fmt,...)
static void method_machine_destroy(void *msm)
static void send_abort_to_initiator(long reason, long handle)
static WAPEvent * make_abort(long reason, long handle)
static int resume_enabled
static List * make_reply_headers(WSPMachine *m)
static wap_dispatch_func_t * dispatch_to_wtp_init
static void cant_handle_event(WSPMachine *sm, WAPEvent *event)
List * http_header_duplicate(List *headers)
Octstr * wsp_cap_pack_list(List *caps_list)
void wsp_session_dispatch_event(WAPEvent *event)
static void indicate_pushabort(WSPPushMachine *machine, long reason)
static void disconnect_other_sessions(WSPMachine *sm)
long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos)
static List * make_capabilities_reply(WSPMachine *m)
static int method_is_holding(void *item, void *pattern)
void gwlist_add_producer(List *list)
int octstr_get_char(const Octstr *ostr, long pos)
static void send_abort(long reason, long handle)
static Counter * session_id_counter
void wsp_cap_destroy(Capability *cap)
WSP_PDU * wsp_pdu_unpack(Octstr *data)
static wap_dispatch_func_t * dispatch_to_ota
void wap_event_destroy(WAPEvent *event)
void wap_dispatch_func_t(WAPEvent *event)
static char * state_name(WSPState state)
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)