/****************************************************************************** * * EXTERNAL FUNCTIONS: * * Handles a possible concatenated message. Creates a list of wap events. */ List *wtp_unpack_wdp_datagram(WAPEvent *datagram) { List *events = NULL; WAPEvent *event = NULL; WAPEvent *subdgram = NULL; Octstr *data = NULL; long pdu_len; gw_assert(datagram->type == T_DUnitdata_Ind); events = gwlist_create(); if (concatenated_message(datagram->u.T_DUnitdata_Ind.user_data)) { data = octstr_duplicate(datagram->u.T_DUnitdata_Ind.user_data); octstr_delete(data, 0, 1); while (octstr_len(data) != 0) { if (octstr_get_bits(data, 0, 1) == 0) { pdu_len = octstr_get_char(data, 0); octstr_delete(data, 0, 1); } else { pdu_len = octstr_get_bits(data, 1, 15); octstr_delete(data, 0, 2); } subdgram = wap_event_duplicate(datagram); octstr_destroy(subdgram->u.T_DUnitdata_Ind.user_data); subdgram->u.T_DUnitdata_Ind.user_data = octstr_copy(data, 0, pdu_len); wap_event_assert(subdgram); if ((event = unpack_wdp_datagram_real(subdgram)) != NULL) { wap_event_assert(event); gwlist_append(events, event); } octstr_delete(data, 0, pdu_len); wap_event_destroy(subdgram); } octstr_destroy(data); } else if ((event = unpack_wdp_datagram_real(datagram)) != NULL) { wap_event_assert(event); gwlist_append(events, event); } else { warning(0, "WTP: Dropping unhandled datagram data:"); octstr_dump(datagram->u.T_DUnitdata_Ind.user_data, 0, GW_WARNING); } return events; }
static void main_thread(void *arg) { WAPEvent *e; WSPMachine *sm; WSP_PDU *pdu; while (run_status == running && (e = gwlist_consume(queue)) != NULL) { wap_event_assert(e); switch (e->type) { case TR_Invoke_Ind: pdu = wsp_pdu_unpack(e->u.TR_Invoke_Ind.user_data); if (pdu == NULL) { warning(0, "WSP: Broken PDU ignored."); wap_event_destroy(e); continue; } break; default: pdu = NULL; break; } sm = find_session_machine(e, pdu); if (sm == NULL) { wap_event_destroy(e); } else { handle_session_event(sm, e, pdu); } wsp_pdu_destroy(pdu); } }
void wap_event_destroy(WAPEvent *event) { if (event == NULL) return; wap_event_assert(event); switch (event->type) { #define WAPEVENT(name, prettyname, fields) \ case name: \ { struct name *p = &event->u.name; fields; } \ break; #define OCTSTR(name) octstr_destroy(p->name); #define OPTIONAL_OCTSTR(name) octstr_destroy(p->name); #define INTEGER(name) p->name = 0; #ifdef HAVE_WTLS_OPENSSL #define WTLSPDUS(name) wtls_pldList_destroy(p->name); #endif /* HAVE_WTLS_OPENSSL */ #define HTTPHEADER(name) http_destroy_headers(p->name); #define ADDRTUPLE(name) wap_addr_tuple_destroy(p->name); #define CAPABILITIES(name) wsp_cap_destroy_list(p->name); #include "wap_events.def" default: panic(0, "Unknown WAPEvent type %d", (int) event->type); } gw_free(event); }
/* * Feed an event to a WSP push client state machine. Do not report errors to * the caller. */ static void push_client_event_handle(WSPPushClientMachine *cpm, WAPEvent *e) { WAPEvent *wtp_event; WSP_PDU *pdu = NULL; wap_event_assert(e); gw_assert(cpm); if (e->type == TR_Invoke_Ind) { pdu = wsp_pdu_unpack(e->u.TR_Invoke_Ind.user_data); /* * Class 1 tests here * Case 4, no session matching address quadruplet, handled by the session mach- * ine. * Tests from table WSP, page 45. Case 5, a PDU state tables cannot handle. */ if (pdu == NULL || pdu->type != ConfirmedPush) { wap_event_destroy(e); wtp_event = send_abort_to_responder(cpm, PROTOERR); wtp_resp_dispatch_event(wtp_event); return; } } debug("wap.wsp", 0, "WSP_PUSH: WSPPushClientMachine %ld, state %s," " event %s", cpm->client_push_id, name_push_client_state(cpm->state), wap_event_name(e->type)); #define PUSH_CLIENT_STATE_NAME(state) #define ROW(push_state, event_type, condition, action, next_state) \ if (cpm->state == push_state && \ e->type == event_type && \ (condition)) { \ action \ cpm->state = next_state; \ debug("wap.wsp", 0, "WSP_PUSH %ld: new state %s", \ cpm->client_push_id, #next_state); \ } else #include "wsp_push_client_states.def" { error(0, "WSP_PUSH: handle_event: unhandled event!"); debug("wap.wsp", 0, "Unhandled event was:"); wap_event_dump(e); wap_event_destroy(e); return; } wsp_pdu_destroy(pdu); wap_event_destroy(e); if (cpm->state == PUSH_CLIENT_NULL_STATE) push_client_machine_destroy(cpm); }
void wsp_session_dispatch_event(WAPEvent *event) { wap_event_assert(event); gwlist_produce(queue, event); }
WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram) { WTP_PDU *pdu; WAPEvent *event; Octstr *data; gw_assert(datagram->type == T_DUnitdata_Ind); data = datagram->u.T_DUnitdata_Ind.user_data; if (truncated_datagram(datagram)) { warning(0, "WTP: got a truncated datagram, ignoring"); return NULL; } pdu = wtp_pdu_unpack(data); /* * wtp_pdu_unpack returned NULL, we have send here a rcv error event, * but now we silently drop the packet. Because we can't figure out * in the pack_error() call if the TID value and hence the direction * inditation is really for initiator or responder. */ if (pdu == NULL) { error(0, "WTP: cannot unpack pdu, dropping packet."); return NULL; } event = NULL; switch (pdu->type) { case Invoke: event = unpack_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); /* if an WTP initiator gets invoke, it would be an illegal pdu. */ if (!wtp_event_is_for_responder(event)){ debug("wap.wtp", 0, "WTP: Invoke when initiator. Message was"); wap_event_destroy(event); event = pack_error(datagram); } break; case Segmented_invoke: event = unpack_segmented_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; case Result: event = unpack_result(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); /* if an WTP responder gets result, it would be an illegal pdu. */ if (wtp_event_is_for_responder(event)){ debug("wap.wtp", 0, "WTP: Result when responder. Message was"); wap_event_destroy(event); event = pack_error(datagram); } break; case Ack: event = unpack_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; case Negative_ack: event = unpack_negative_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; case Abort: event = unpack_abort(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; default: event = pack_error(datagram); debug("wap.wtp", 0, "WTP: Unhandled PDU type. Message was"); wap_event_dump(datagram); return event; } wtp_pdu_destroy(pdu); wap_event_assert(event); return event; }
WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram) { WTP_PDU *pdu; WAPEvent *event; Octstr *data; gw_assert(datagram->type == T_DUnitdata_Ind); data = datagram->u.T_DUnitdata_Ind.user_data; if (truncated_datagram(datagram)) { warning(0, "WTP: got a truncated datagram, ignoring"); return NULL; } pdu = wtp_pdu_unpack(data); /* * Wtp_pdu_unpack returned NULL, we build a rcv error event. */ if (pdu == NULL) { error(0, "WTP: cannot unpack pdu, creating an error pdu"); event = pack_error(datagram); return event; } event = NULL; switch (pdu->type) { case Invoke: event = unpack_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); /* if an WTP initiator gets invoke, it would be an illegal pdu. */ if (!wtp_event_is_for_responder(event)){ debug("wap.wtp", 0, "WTP: Invoke when initiator. Message was"); wap_event_destroy(event); event = pack_error(datagram); } break; case Segmented_invoke: event = unpack_segmented_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; case Result: event = unpack_result(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); /* if an WTP responder gets result, it would be an illegal pdu. */ if (wtp_event_is_for_responder(event)){ debug("wap.wtp", 0, "WTP: Result when responder. Message was"); wap_event_destroy(event); event = pack_error(datagram); } break; case Ack: event = unpack_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; case Negative_ack: event = unpack_negative_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; case Abort: event = unpack_abort(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple); break; default: event = pack_error(datagram); debug("wap.wtp", 0, "WTP: Unhandled PDU type. Message was"); wap_event_dump(datagram); return event; } wtp_pdu_destroy(pdu); wap_event_assert(event); return event; }