📄 wtp_init.c
字号:
*/ 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, event->u.TR_Invoke_Req.handle, event->u.TR_Invoke_Req.tcl); /* if SAR needed */ if (octstr_len(event->u.TR_Invoke_Req.user_data) > SAR_SEGM_SIZE) { machine->sar = gw_malloc(sizeof(WTPSARData)); machine->sar->nsegm = 0; machine->sar->csegm = 0; machine->sar->lsegm = 0; machine->sar->data = NULL; } 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; } } else { switch(event->type) { case RcvResult: /* if SAR requested */ if (!event->u.RcvResult.gtr || !event->u.RcvResult.ttr) { machine->sar = gw_malloc(sizeof(WTPSARData)); machine->sar->nsegm = 0; machine->sar->csegm = 0; machine->sar->lsegm = 0; machine->sar->data = NULL; } break; default: break; } } return machine;}/* * Creates TR-Invoke.cnf event */static WAPEvent *create_tr_invoke_cnf(WTPInitMachine *init_machine) { WAPEvent *event; gw_assert(init_machine != NULL); event = wap_event_create(TR_Invoke_Cnf); event->u.TR_Invoke_Cnf.handle = init_machine->mid; event->u.TR_Invoke_Cnf.addr_tuple = wap_addr_tuple_duplicate(init_machine->addr_tuple); return event;}/* * Creates TR-Abort.ind event from an initiator state machine. In addtion, set * the ir_flag on. */static WAPEvent *create_tr_abort_ind(WTPInitMachine *sm, long abort_reason) { WAPEvent *event; event = wap_event_create(TR_Abort_Ind); event->u.TR_Abort_Ind.abort_code = abort_reason; event->u.TR_Abort_Ind.addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple); event->u.TR_Abort_Ind.handle = sm->mid; event->u.TR_Abort_Ind.ir_flag = INITIATOR_INDICATION; return event;}static int tid_wrapped(unsigned short tid) { return tid > (1 << 15);}static unsigned short rcv_tid(unsigned short tid) { return tid ^ 0x8000;}/* * Start retry interval timer (strictly speaking, timer iniatilised with retry * interval). Multiply timer value with init_timer_freq. */static void start_initiator_timer_R(WTPInitMachine *machine) { WAPEvent *timer_event; int seconds; timer_event = wap_event_create(TimerTO_R); timer_event->u.TimerTO_R.handle = machine->mid; if (machine->u_ack) seconds = S_R_WITH_USER_ACK * init_timer_freq; else seconds = S_R_WITHOUT_USER_ACK * init_timer_freq; gwtimer_start(machine->timer, seconds, timer_event);}static void start_initiator_timer_A(WTPInitMachine *machine) { WAPEvent *timer_event; int seconds; timer_event = wap_event_create(TimerTO_A); timer_event->u.TimerTO_A.handle = machine->mid; if (machine->u_ack) seconds = S_R_WITH_USER_ACK * init_timer_freq; else seconds = S_R_WITHOUT_USER_ACK * init_timer_freq; gwtimer_start(machine->timer, seconds, timer_event);}static void start_initiator_timer_W(WTPInitMachine *machine) { WAPEvent *timer_event; int seconds; timer_event = wap_event_create(TimerTO_W); timer_event->u.TimerTO_W.handle = machine->mid; if (machine->u_ack) seconds = S_R_WITH_USER_ACK * init_timer_freq; else seconds = S_R_WITHOUT_USER_ACK * init_timer_freq; gwtimer_start(machine->timer, seconds, timer_event);}static void stop_initiator_timer(Timer *timer) { debug("wap.wtp_init", 0, "stopping timer"); gw_assert(timer); gwtimer_stop(timer);}static void send_abort(WTPInitMachine *machine, long type, long reason) { WAPEvent *e; e = wtp_pack_abort(type, reason, machine->tid, machine->addr_tuple); dispatch_to_wdp(e);}static void send_ack(WTPInitMachine *machine, long ack_type, int rid_flag) { WAPEvent *e; e = wtp_pack_ack(ack_type, rid_flag, machine->tid, machine->addr_tuple); dispatch_to_wdp(e);}/* * Process incoming event, checking for WTP SAR */static int process_sar_transaction(WTPInitMachine *machine, WAPEvent **event) { WAPEvent *e, *orig_event; int psn; orig_event = *event; if (orig_event->type == RcvResult) { if (!orig_event->u.RcvResult.ttr || !orig_event->u.RcvResult.gtr) { /* SAR */ /* Ericcson set TTR flag even if we have the only part */ if (orig_event->u.RcvResult.ttr == 1) { return 1; /* Not SAR although TTR flag was set */ } else { /* save initial event */ machine->sar_invoke = wap_event_duplicate(orig_event); /* save data into list with psn = 0 */ add_sar_transaction(machine, orig_event->u.RcvResult.user_data, 0); if (orig_event->u.RcvResult.gtr == 1) { /* Need to acknowledge */ e = wtp_pack_sar_ack(ACKNOWLEDGEMENT, machine->tid, machine->addr_tuple, 0); dispatch_to_wdp(e); } return 0; } } else { return 1; /* Not SAR */ } } if (orig_event->type == RcvSegResult) { add_sar_transaction(machine, orig_event->u.RcvSegResult.user_data, orig_event->u.RcvSegResult.psn); if (orig_event->u.RcvSegResult.gtr == 1) { /* Need to acknowledge */ e = wtp_pack_sar_ack(ACKNOWLEDGEMENT, machine->tid, machine->addr_tuple, orig_event->u.RcvSegResult.psn); dispatch_to_wdp(e); } if (orig_event->u.RcvSegResult.ttr == 1) { /* Need to feed to WSP */ /* Create assembled event */ psn = orig_event->u.RcvSegResult.psn; wap_event_destroy(orig_event); *event = assembly_sar_event(machine,psn); gw_assert(event != NULL); return 1; } return 0; } /* Not SAR message */ return 1;}static int is_wanted_sar_data(void *a, void *b){ sar_info_t *s; int *i; s = a; i = b; if (*i == s->sar_psn) { return 1; } else { return 0; }}/* * Return 0 if transaction added suscessufully, 1 otherwise. */static int add_sar_transaction(WTPInitMachine *machine, Octstr *data, int psn) { sar_info_t *sar_info; if (machine->sar_info == NULL) { machine->sar_info = list_create(); } if (list_search(machine->sar_info, &psn, is_wanted_sar_data) == NULL) { sar_info = gw_malloc(sizeof(sar_info_t)); sar_info->sar_psn = psn; sar_info->sar_data = octstr_duplicate(data); list_append(machine->sar_info, sar_info); return 0; } else { debug("wap.wtp", 0, "Duplicated psn found, ignore packet"); return 1; } }static WAPEvent *assembly_sar_event(WTPInitMachine *machine, int last_psn) { WAPEvent *e; int i; sar_info_t *sar_info; e = wap_event_duplicate(machine->sar_invoke); for (i = 1; i <= last_psn; i++) { if ((sar_info = list_search(machine->sar_info, &i, is_wanted_sar_data)) != NULL) { octstr_append(e->u.RcvResult.user_data, sar_info->sar_data); } else { debug("wap.wtp", 0, "Packet with psn %d not found", i); return e; } } return e;}static void sar_info_destroy(void *p) { sar_info_t *sar_info; sar_info = p; octstr_destroy(sar_info->sar_data); gw_free(sar_info);}static void sardata_destroy(void *p) { WTPSARData * sardata; if (p) { sardata = p; octstr_destroy(sardata->data); gw_free(sardata); }}static void begin_sar_invoke(WTPInitMachine *init_machine, WAPEvent *event) { WAPEvent *invoke; WTPSARData *sar; int psn; gw_assert(init_machine->sar != NULL); sar = init_machine->sar; sar->data = octstr_duplicate(event->u.TR_Invoke_Req.user_data); sar->nsegm = (octstr_len(sar->data)-1)/SAR_SEGM_SIZE; sar->tr = sar->lsegm = 0; sar->csegm = -1; debug("wap.wtp", 0, "WTP: begin_sar_invoke(): data len = %lu", octstr_len(sar->data)); for (psn = 0; !sar->tr; psn++) { invoke = wtp_pack_sar_invoke(init_machine, psn); if (sar->tr) init_machine->invoke = wap_event_duplicate(invoke); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn); dispatch_to_wdp(invoke); sar->lsegm = psn; } init_machine->rid = 1;}static void continue_sar_invoke(WTPInitMachine *init_machine, WAPEvent *event) { WAPEvent *invoke; WTPSARData *sar; int psn; gw_assert(init_machine->sar != NULL && event->type == RcvAck); sar = init_machine->sar; debug("wap.wtp", 0, "WTP: continue_sar_invoke(): lsegm=%d, nsegm=%d, csegm=%d", sar->lsegm, sar->nsegm, sar->csegm); start_initiator_timer_R(init_machine); if (event->u.RcvAck.psn>sar->csegm) { sar->csegm = event->u.RcvAck.psn; } sar->tr = 0; wap_event_destroy(init_machine->invoke); init_machine->invoke = NULL; for (psn = sar->csegm + 1; !sar->tr; psn++) { invoke = wtp_pack_sar_invoke(init_machine, psn); if (sar->tr) init_machine->invoke = wap_event_duplicate(invoke); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u",psn); dispatch_to_wdp(invoke); sar->lsegm = psn; }}static void resend_sar_invoke(WTPInitMachine *init_machine, WAPEvent *event){ WAPEvent *invoke; WTPSARData *sar; int psn, i; gw_assert(init_machine->sar != NULL && event->type == RcvNegativeAck); sar = init_machine->sar; debug("wap.wtp", 0, "WTP: resend_sar_invoke(): lsegm=%d, nsegm=%d, csegm=%d", sar->lsegm, sar->nsegm, sar->csegm); start_initiator_timer_R(init_machine); if (event->u.RcvNegativeAck.nmissing) { /* if we have a list of missed packets */ for(i = 0; i < event->u.RcvNegativeAck.nmissing; i++) { if ((psn = octstr_get_char(event->u.RcvNegativeAck.missing, i)) >= 0) { invoke = wtp_pack_sar_invoke(init_machine, psn); wtp_pack_set_rid(invoke, 1); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn); dispatch_to_wdp(invoke); } } } else { /* if we have to resend a whole group */ sar->tr = 0; for (psn = sar->csegm+1; !sar->tr; psn++) { invoke = wtp_pack_sar_invoke(init_machine, psn); wtp_pack_set_rid(invoke, 1); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn); dispatch_to_wdp(invoke); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -