static void handle_ota_event(WAPEvent *e) { debug("wap.push.ota", 0, "OTA: event arrived"); switch (e->type) { case Pom_SessionRequest_Req: make_session_request(e); break; case Po_Push_Req: make_push_request(e); break; case Po_ConfirmedPush_Req: make_confirmed_push_request(e); break; case Po_Unit_Push_Req: make_unit_push_request(e); break; case Po_PushAbort_Req: abort_push(e); break; default: debug("wap.push.ota", 0, "OTA: unhandled event"); wap_event_dump(e); break; } wap_event_destroy(e); }
static void wtp_event_dump(Msg *msg) { WAPEvent *dgram; List *events; long i, n; dgram = wdp_msg2event(msg); if (dgram == NULL) error(0, "dgram is null"); /* pdu = wtp_pdu_unpack(dgram->u.T_DUnitdata_Ind.user_data); if (pdu == NULL) { error(0, "WTP PDU unpacking failed, WAP event is:"); wap_event_dump(dgram); } else { wtp_pdu_dump(pdu, 0); wtp_pdu_destroy(pdu); } */ events = wtp_unpack_wdp_datagram(dgram); n = gwlist_len(events); debug("wap.proxy",0,"datagram contains %ld events", n); i = 1; while (gwlist_len(events) > 0) { WAPEvent *event; event = gwlist_extract_first(events); info(0, "WTP: %ld/%ld event %s.", i, n, wap_event_name(event->type)); if (wtp_event_is_for_responder(event)) /* wtp_resp_dispatch_event(event); */ debug("",0,"datagram is for WTP responder"); else /* wtp_initiator_dispatch_event(event); */ debug("",0,"datagram is for WTP initiator"); wap_event_dump(event); /* switch (event->type) { RcvInvoke: debug("",0,"XXX invoke"); break; RcvResult: debug("",0,"XXX result"); break; default: error(0,"unkown WTP event type while unpacking"); break; } */ i++; } wap_event_destroy(dgram); gwlist_destroy(events, NULL); }
/* * Responder set the first bit of the tid field. If we get a packet from the * responder, we are the initiator and vice versa. * * Return 1, when the event is for responder, 0 when it is for initiator and * -1 when error. */ int wtp_event_is_for_responder(WAPEvent *event) { switch(event->type){ case RcvInvoke: return event->u.RcvInvoke.tid < INITIATOR_TID_LIMIT; case RcvSegInvoke: return event->u.RcvSegInvoke.tid < INITIATOR_TID_LIMIT; case RcvResult: return event->u.RcvResult.tid < INITIATOR_TID_LIMIT; case RcvAck: return event->u.RcvAck.tid < INITIATOR_TID_LIMIT; case RcvNegativeAck: return event->u.RcvNegativeAck.tid < INITIATOR_TID_LIMIT; case RcvAbort: return event->u.RcvAbort.tid < INITIATOR_TID_LIMIT; case RcvErrorPDU: return event->u.RcvErrorPDU.tid < INITIATOR_TID_LIMIT; default: error(1, "Received an erroneous PDU corresponding an event"); wap_event_dump(event); return -1; } }
static void wdp_event_dump(Msg *msg) { WAPEvent *dgram; if ((dgram = wdp_msg2event(msg)) != NULL) /* wap_dispatch_datagram(dgram); */ wap_event_dump(dgram); wap_event_destroy(dgram); }
/* * 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); }
/***************************************************************************** * * INTERNAL FUNCTIONS: * * If pdu was truncated, tid cannot be trusted. We ignore this message. */ static int truncated_datagram(WAPEvent *dgram) { gw_assert(dgram->type == T_DUnitdata_Ind); if (octstr_len(dgram->u.T_DUnitdata_Ind.user_data) < 3) { debug("wap.wtp", 0, "A too short PDU received"); wap_event_dump(dgram); return 1; } else return 0; }
static void cant_handle_event(WSPMachine *sm, WAPEvent *event) { /* We do the rest of the pre-state-machine tests here. The first * four were done in find_session_machine(). The fifth is a * class 1 or 2 TR-Invoke.ind not handled by the state tables. */ if (event->type == TR_Invoke_Ind && (event->u.TR_Invoke_Ind.tcl == 1 || event->u.TR_Invoke_Ind.tcl == 2)) { warning(0, "WSP: Can't handle TR-Invoke.ind, aborting transaction."); debug("wap.wsp", 0, "WSP: The unhandled event:"); wap_event_dump(event); send_abort(WSP_ABORT_PROTOERR, event->u.TR_Invoke_Ind.handle); /* The sixth is a class 0 TR-Invoke.ind not handled by state tables. */ } else if (event->type == TR_Invoke_Ind) { warning(0, "WSP: Can't handle TR-Invoke.ind, ignoring."); debug("wap.wsp", 0, "WSP: The ignored event:"); wap_event_dump(event); /* The seventh is any other event not handled by state tables. */ } else { error(0, "WSP: Can't handle event. Aborting session."); debug("wap.wsp", 0, "WSP: The unhandled event:"); wap_event_dump(event); /* TR-Abort.req(PROTOERR) if it is some other transaction * event than abort. */ /* Currently that means TR-Result.cnf, because we already * tested for Invoke. */ /* FIXME We need a better way to get at event values than * by hardcoding the types. */ if (event->type == TR_Result_Cnf) { send_abort(WSP_ABORT_PROTOERR, event->u.TR_Result_Cnf.handle); } /* Abort(PROTOERR) all method and push transactions */ abort_methods(sm, WSP_ABORT_PROTOERR); abort_pushes(sm, WSP_ABORT_PROTOERR); /* S-Disconnect.ind(PROTOERR) */ indicate_disconnect(sm, WSP_ABORT_PROTOERR); } }
/* * Add push flag into push headers. Push flag is defined in ota, p. 17-18. * If there is no flags set, no Push-Flag header is added. */ static List *add_push_flag(WAPEvent *e) { int push_flag, trusted, authenticated, last; Octstr *buf; List *headers; flags_assert(e); if (e->type == Po_Unit_Push_Req) { trusted = e->u.Po_Unit_Push_Req.trusted << 1; authenticated = e->u.Po_Unit_Push_Req.authenticated; last = e->u.Po_Unit_Push_Req.last << 2; headers = http_header_duplicate(e->u.Po_Unit_Push_Req.push_headers); } else if (e->type == Po_Push_Req) { trusted = e->u.Po_Push_Req.trusted << 1; authenticated = e->u.Po_Push_Req.authenticated; last = e->u.Po_Push_Req.last << 2; headers = http_header_duplicate(e->u.Po_Push_Req.push_headers); } else if (e->type == Po_ConfirmedPush_Req) { trusted = e->u.Po_ConfirmedPush_Req.trusted << 1; authenticated = e->u.Po_ConfirmedPush_Req.authenticated; last = e->u.Po_ConfirmedPush_Req.last << 2; headers = http_header_duplicate( e->u.Po_ConfirmedPush_Req.push_headers); } else { debug("wap.ota", 0, "OTA: no push flag when the event is: \n"); wap_event_dump(e); return NULL; } push_flag = 0; push_flag = push_flag | authenticated | trusted | last; if (push_flag) { buf = octstr_format("%d", push_flag); http_header_add(headers, "Push-Flag", octstr_get_cstr(buf)); octstr_destroy(buf); } return headers; }
/* * Send IP datagram as it is, segment SMS datagram if necessary. */ static void dispatch_datagram(WAPEvent *dgram) { Msg *msg, *part; List *sms_datagrams; static unsigned long msg_sequence = 0L; /* Used only by this function */ msg = part = NULL; sms_datagrams = NULL; if (dgram == NULL) { error(0, "WDP: dispatch_datagram received empty datagram, ignoring."); } else if (dgram->type != T_DUnitdata_Req) { warning(0, "WDP: dispatch_datagram received event of unexpected type."); wap_event_dump(dgram); } else if (dgram->u.T_DUnitdata_Req.address_type == ADDR_IPV4) { #ifdef HAVE_WTLS_OPENSSL if (dgram->u.T_DUnitdata_Req.addr_tuple->local->port >= WTLS_CONNECTIONLESS_PORT) wtls_dispatch_resp(dgram); else #endif /* HAVE_WTLS_OPENSSL */ { msg = pack_ip_datagram(dgram); write_to_bearerbox(msg); } } else { msg_sequence = counter_increase(sequence_counter) & 0xff; msg = pack_sms_datagram(dgram); sms_datagrams = sms_split(msg, NULL, NULL, NULL, NULL, concatenation, msg_sequence, max_messages, MAX_SMS_OCTETS); debug("wap",0,"WDP (wapbox): delivering %ld segments to bearerbox", gwlist_len(sms_datagrams)); while ((part = gwlist_extract_first(sms_datagrams)) != NULL) { write_to_bearerbox(part); } gwlist_destroy(sms_datagrams, NULL); msg_destroy(msg); } wap_event_destroy(dgram); }
/* This function does NOT consume its event; it leaves that task up * to the parent session */ static void handle_method_event(WSPMachine *sm, WSPMethodMachine *msm, WAPEvent *current_event, WSP_PDU *pdu) { if (msm == NULL) { warning(0, "No method machine for event."); wap_event_dump(current_event); return; } debug("wap.wsp", 0, "WSP: method %ld, state %s, event %s", msm->transaction_id, state_name(msm->state), wap_event_name(current_event->type)); gw_assert(sm->session_id == msm->session_id); #define STATE_NAME(name) #define ROW(state_name, event, condition, action, next_state) \ { \ struct event *e; \ e = ¤t_event->u.event; \ if (msm->state == state_name && \ current_event->type == event && \ (condition)) { \ action \ msm->state = next_state; \ debug("wap.wsp", 0, "WSP %ld/%ld: New method state %s", \ msm->session_id, msm->transaction_id, #next_state); \ goto end; \ } \ } #include "wsp_server_method_states.def" cant_handle_event(sm, current_event); end: if (msm->state == NULL_METHOD) { method_machine_destroy(msm); gwlist_delete_equal(sm->methodmachines, msm); } }
/* * Feed an event to a WTP initiator state machine. Handle all errors by do not * report them to the caller. WSP indication or conformation is handled by an * included state table. Note: Do not put {}s of the else block inside the * macro definition . */ static void handle_init_event(WTPInitMachine *init_machine, WAPEvent *event) { WAPEvent *wsp_event = NULL; debug("wap.wtp", 0, "WTP_INIT: initiator machine %ld, state %s," " event %s.", init_machine->mid, name_init_state(init_machine->state), wap_event_name(event->type)); #define INIT_STATE_NAME(state) #define ROW(init_state, event_type, condition, action, next_state) \ if (init_machine->state == init_state && \ event->type == event_type && \ (condition)) { \ action \ init_machine->state = next_state; \ debug("wap.wtp", 0, "WTP_INIT %ld: New state %s", \ init_machine->mid, #next_state); \ } else #include "wtp_init_states.def" { error(1, "WTP_INIT: handle_init_event: unhandled event!"); debug("wap.wtp.init", 0, "WTP_INIT: handle_init_event:" "Unhandled event was:"); wap_event_dump(event); wap_event_destroy(event); return; } if (event != NULL) { wap_event_destroy(event); } if (init_machine->state == INITIATOR_NULL_STATE) init_machine_destroy(init_machine); }
static void handle_push_event(WSPMachine *sm, WSPPushMachine *pm, WAPEvent *current_event) { if (pm == NULL) { warning(0, "No push machine for event."); wap_event_dump(current_event); return; } debug("wap.wsp", 0, "WSP(tid/pid): push %ld/%ld, state %s, event %s", pm->transaction_id, pm->server_push_id, state_name(pm->state), wap_event_name(current_event->type)); gw_assert(sm->session_id == pm->session_id); #define STATE_NAME(name) #define ROW(state_name, event, condition, action, next_state) \ { \ if (pm->state == state_name && \ current_event->type == event && \ (condition)) { \ action \ pm->state = next_state; \ debug("wap.wsp", 0, "WSP %ld/%ld: New push state %s", \ pm->session_id, pm->transaction_id, #next_state); \ goto end; \ } \ } #include "wsp_server_push_states.def" cant_handle_event(sm, current_event); end: if (pm->state == SERVER_PUSH_NULL_STATE) { push_machine_destroy(pm); gwlist_delete_equal(sm->pushmachines, pm); } }
static WSPMachine *find_session_machine(WAPEvent *event, WSP_PDU *pdu) { WSPMachine *sm; long session_id; WAPAddrTuple *tuple; tuple = NULL; session_id = -1; switch (event->type) { case TR_Invoke_Ind: tuple = wap_addr_tuple_duplicate( event->u.TR_Invoke_Ind.addr_tuple); break; case TR_Invoke_Cnf: tuple = wap_addr_tuple_duplicate( event->u.TR_Invoke_Cnf.addr_tuple); break; case TR_Result_Cnf: tuple = wap_addr_tuple_duplicate( event->u.TR_Result_Cnf.addr_tuple); break; case TR_Abort_Ind: tuple = wap_addr_tuple_duplicate( event->u.TR_Abort_Ind.addr_tuple); break; case S_Connect_Res: session_id = event->u.S_Connect_Res.session_id; break; case S_Resume_Res: session_id = event->u.S_Resume_Res.session_id; break; case Disconnect_Event: session_id = event->u.Disconnect_Event.session_handle; break; case Suspend_Event: session_id = event->u.Suspend_Event.session_handle; break; case S_MethodInvoke_Res: session_id = event->u.S_MethodInvoke_Res.session_id; break; case S_MethodResult_Req: session_id = event->u.S_MethodResult_Req.session_id; break; case S_ConfirmedPush_Req: session_id = event->u.S_ConfirmedPush_Req.session_id; break; case S_Push_Req: session_id = event->u.S_Push_Req.session_id; break; default: error(0, "WSP: Cannot find machine for %s event", wap_event_name(event->type)); } gw_assert(tuple != NULL || session_id != -1); /* Pre-state-machine tests, according to 7.1.5. After the tests, * caller will pass the event to sm if sm is not NULL. */ sm = NULL; /* First test is for MRUEXCEEDED, and we don't have a MRU */ /* Second test is for class 2 TR-Invoke.ind with Connect PDU */ if (event->type == TR_Invoke_Ind && event->u.TR_Invoke_Ind.tcl == 2 && pdu->type == Connect) { /* Create a new session, even if there is already * a session open for this address. The new session * will take care of killing the old ones. */ sm = machine_create(); gw_assert(tuple != NULL); sm->addr_tuple = wap_addr_tuple_duplicate(tuple); sm->connect_handle = event->u.TR_Invoke_Ind.handle; /* Third test is for class 2 TR-Invoke.ind with Resume PDU */ } else if (event->type == TR_Invoke_Ind && event->u.TR_Invoke_Ind.tcl == 2 && pdu->type == Resume) { /* Pass to session identified by session id, not * the address tuple. */ session_id = pdu->u.Resume.sessionid; sm = gwlist_search(session_machines, &session_id, find_by_session_id); if (sm == NULL) { /* No session; TR-Abort.req(DISCONNECT) */ send_abort(WSP_ABORT_DISCONNECT, event->u.TR_Invoke_Ind.handle); } /* Fourth test is for a class 1 or 2 TR-Invoke.Ind with no * session for that address tuple. We also handle class 0 * TR-Invoke.ind here by ignoring them; this seems to be * an omission in the spec table. */ } else if (event->type == TR_Invoke_Ind) { sm = gwlist_search(session_machines, tuple, transaction_belongs_to_session); if (sm == NULL && (event->u.TR_Invoke_Ind.tcl == 1 || event->u.TR_Invoke_Ind.tcl == 2)) { send_abort(WSP_ABORT_DISCONNECT, event->u.TR_Invoke_Ind.handle); } /* Other tests are for events not handled by the state tables; * do those later, after we've tried to handle them. */ } else { if (session_id != -1) { sm = gwlist_search(session_machines, &session_id, find_by_session_id); } else { sm = gwlist_search(session_machines, tuple, transaction_belongs_to_session); } /* The table doesn't really say what we should do with * non-Invoke events for which there is no session. But * such a situation means there is an error _somewhere_ * in the gateway. */ if (sm == NULL) { error(0, "WSP: Cannot find session machine for event."); wap_event_dump(event); } } wap_addr_tuple_destroy(tuple); return sm; }
/* * Checks client push machines list for a specific machine. Creates it, if the * event is TR-Invoke.ind. * Client push machine is identified (when searching) by transcation identifi- * er. * Note that only WTP responder send its class 1 messages to client push state * machine. So, it is no need to specify WTP machine type. */ static WSPPushClientMachine *push_client_machine_find_or_create(WAPEvent *e) { WSPPushClientMachine *cpm; long transid; cpm = NULL; transid = -1; switch (e->type) { case TR_Invoke_Ind: transid = e->u.TR_Invoke_Ind.handle; break; case S_ConfirmedPush_Res: transid = e->u.S_ConfirmedPush_Res.client_push_id; break; case S_PushAbort_Req: transid = e->u.S_PushAbort_Req.push_id; break; case Abort_Event: break; case TR_Abort_Ind: transid = e->u.TR_Abort_Ind.handle; break; default: debug("wap.wsp", 0, "WSP PUSH: push_client_find_or_create: unhandled" " event"); wap_event_dump(e); wap_event_destroy(e); return NULL; } gw_assert(transid != -1); cpm = push_client_machine_find_using_transid(transid); if (cpm == NULL) { switch (e->type) { case TR_Invoke_Ind: cpm = push_client_machine_create(transid); break; case S_ConfirmedPush_Res: case S_PushAbort_Req: error(0, "WSP_PUSH_CLIENT: POT primitive to a nonexisting" " push client machine"); break; case Abort_Event: error(0, "WSP_PUSH_CLIENT: internal abort to a nonexisting" " push client machine"); break; case TR_Abort_Ind: error(0, "WSP_PUSH_CLIENT: WTP abort to a nonexisting push client" " machine"); break; default: error(0, "WSP_PUSH_CLIENT: Cannot handle event type %s", wap_event_name(e->type)); break; } } return cpm; }
static WTLSMachine *wtls_machine_find_or_create(WAPEvent * event) { WTLSMachine *wtls_machine = NULL; long mid; WAPAddrTuple *tuple; tuple = NULL; mid = -1; debug("wap.wtls", 0, "event->type = %d", event->type); /* Get the address that this PDU came in from */ switch (event->type) { case T_Unitdata_Ind: case T_DUnitdata_Ind: tuple = event->u.T_Unitdata_Ind.addr_tuple; break; case SEC_Create_Request_Req: case SEC_Terminate_Req: case SEC_Exception_Req: case SEC_Create_Res: case SEC_Exchange_Req: case SEC_Commit_Req: case SEC_Unitdata_Req: tuple = event->u.T_Unitdata_Ind.addr_tuple; break; default: debug("wap.wtls", 0, "WTLS: wtls_machine_find_or_create:" "unhandled event (1)"); wap_event_dump(event); return NULL; } /* Either the address or the machine id must be available at this point */ gw_assert(tuple != NULL || mid != -1); /* Look for the machine owning this address */ wtls_machine = wtls_machine_find(tuple, mid); /* Oh well, we didn't find one. We'll create one instead, provided it meets certain criteria */ if (wtls_machine == NULL) { switch (event->type) { case SEC_Create_Request_Req: /* State NULL, case 1 */ debug("wap.wtls", 0, "WTLS: received a SEC_Create_Request_Req, and don't know what to do with it..."); /* Create and dispatch a T_Unitdata_Req containing a HelloRequest */ /* And there's no need to do anything else, 'cause we return to state NULL */ break; case T_Unitdata_Ind: case T_DUnitdata_Ind: /* State NULL, case 3 */ /* if (wtls_event_type(event) == Alert_No_Renegotiation) { */ /* Create and dispatch a SEC_Exception_Ind event */ /* debug("wap.wtls",0,"WTLS: received an Alert_no_Renegotiation; just dropped it."); */ /* And there's no need to do anything else, 'cause we return to state NULL */ /* break; */ /* } else */ /* if (event->u.T_Unitdata_Ind == ClientHello) { */ /* State NULL, case 2 */ wtls_machine = wtls_machine_create(tuple); /* And stick said event into machine, which should push us into state CREATING after a SEC_Create_Ind */ /* } */ break; default: error(0, "WTLS: wtls_machine_find_or_create:" " unhandled event (2)"); wap_event_dump(event); break; } } return wtls_machine; }
int main(int argc, char **argv) { int opt, ret; Octstr *pap_doc, *log_file; WAPEvent *e; log_file = NULL; gwlib_init(); while ((opt = getopt(argc, argv, "h:v:l:")) != EOF) { switch (opt) { case 'h': help(); exit(1); break; case 'v': log_set_output_level(atoi(optarg)); break; case 'l': octstr_destroy(log_file); log_file = octstr_create(optarg); break; case '?': default: error(0, "Invalid option %c", opt); help(); panic(0, "Stopping"); break; } } if (optind >= argc) { error(0, "Missing arguments"); help(); panic(0, "Stopping"); } if (log_file != NULL) { log_open(octstr_get_cstr(log_file), GW_DEBUG, GW_NON_EXCL); octstr_destroy(log_file); } pap_doc = octstr_read_file(argv[optind]); if (pap_doc == NULL) panic(0, "Cannot read the pap document"); e = NULL; ret = pap_compile(pap_doc, &e); if (ret < 0) { debug("test.pap", 0, "Unable to compile the pap document, rc %d", ret); return 1; } debug("test.pap", 0, "Compiling successfull, wap event being:\n"); wap_event_dump(e); wap_event_destroy(e); octstr_destroy(pap_doc); gwlib_shutdown(); return 0; }
/* * Checks whether wtp initiator machines data structure includes a specific * machine. The machine in question is identified with with source and * destination address and port and tid. First test incoming events * (WTP 10.2) (Exception are tests nro 4 and 5: if we have a memory error, * we panic (nro 4); nro 5 is already checked). If we have an ack with tid * verification flag set and no corresponding transaction, we abort.(case nro * 2). If the event was a normal ack or an abort, it is ignored (error nro 3). * In the case of TR-Invoke.req a new machine is created, in the case of * TR-Abort.req we have a serious error. We must create a new tid for a new * transaction here, because machines are identified by an address tuple and a * tid. This tid is GenTID (WTP 10.4.2), which is used only by the wtp iniator * thread. * Note that as internal tid representation, module uses RcvTID (as required * by module wtp_pack). So we we turn the first bit of the tid stored by the * init machine. */ static WTPInitMachine *init_machine_find_or_create(WAPEvent *event) { WTPInitMachine *machine = NULL; long mid; static long tid = -1; WAPAddrTuple *tuple; mid = -1; tuple = NULL; switch (event->type) { case RcvAck: tid = event->u.RcvAck.tid; tuple = event->u.RcvAck.addr_tuple; break; case RcvAbort: tid = event->u.RcvAbort.tid; tuple = event->u.RcvAbort.addr_tuple; break; case RcvErrorPDU: mid = event->u.RcvErrorPDU.tid; tid = event->u.RcvErrorPDU.tid; tuple = event->u.RcvErrorPDU.addr_tuple; break; /* * When we are receiving an invoke requirement, we must create a new trans- * action and generate a new tid. This can be wrapped, and should have its * first bit turned. */ case TR_Invoke_Req: ++tid; if (tid_wrapped(tid)) { tidnew = 1; tid = 0; } tid = rcv_tid(tid); tuple = event->u.TR_Invoke_Req.addr_tuple; mid = event->u.TR_Invoke_Req.handle; break; case TR_Abort_Req: tid = event->u.TR_Abort_Req.handle; break; case TimerTO_R: mid = event->u.TimerTO_R.handle; break; default: error(0, "WTP_INIT: machine_find_or_create: unhandled event"); wap_event_dump(event); return NULL; } gw_assert(tuple != NULL || mid != -1); machine = init_machine_find(tuple, tid, mid); if (machine == NULL){ switch (event->type){ case RcvAck: /* * Case nro 2 If we do not have a tid asked for, we send a negative answer, * i.e. an abort with reason INVALIDTID. */ if (event->u.RcvAck.tid_ok) { dispatch_to_wdp(wtp_pack_abort(PROVIDER, INVALIDTID, tid, tuple)); } /* Case nro 3, normal ack */ else info(0, "WTP_INIT: machine_find_or_create: ack " "received, yet having no machine"); break; /* Case nro 3, abort */ case RcvAbort: info(0, "WTP_INIT: machine_find_or_create: abort " "received, yet having no machine"); break; case TR_Invoke_Req: machine = init_machine_create(tuple, tid, tidnew); machine->mid = event->u.TR_Invoke_Req.handle; break; case TR_Abort_Req: error(0, "WTP_INIT: machine_find_or_create: WSP " "primitive to a wrong WTP machine"); break; case TimerTO_R: error(0, "WTP_INIT: machine_find_or_create: timer " "event without a corresponding machine"); break; default: error(0, "WTP_INIT: machine_find_or_create: unhandled" "event"); wap_event_dump(event); break; } } return machine; }
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; }