📄 wtp_resp.c
字号:
resp_machine->sar = gw_malloc(sizeof(WTPSARData)); resp_machine->sar->nsegm = 0; resp_machine->sar->csegm = 0; resp_machine->sar->lsegm = 0; resp_machine->sar->data = NULL; } break; case RcvSegInvoke: info(0, "WTP_RESP: resp_machine_find_or_create:" " segmented invoke received, yet having no machine"); break; /* * This and the following branch implement test nro 3 in WTP 10.2. */ case RcvAck: info(0, "WTP_RESP: resp_machine_find_or_create:" " ack received, yet having no machine"); break; case RcvNegativeAck: info(0, "WTP_RESP: resp_machine_find_or_create:" " negative ack received, yet having no machine"); break; case RcvAbort: info(0, "WTP_RESP: resp_machine_find_or_create:" " abort received, yet having no machine"); break; case TR_Invoke_Res: case TR_Result_Req: case TR_Abort_Req: error(0, "WTP_RESP: resp_machine_find_or_create: WSP primitive to" " a wrong WTP machine"); break; case TimerTO_A: case TimerTO_R: case TimerTO_W: error(0, "WTP_RESP: resp_machine_find_or_create: timer event" " without a corresponding machine"); break; default: error(0, "WTP_RESP: resp_machine_find_or_create: unhandled event"); wap_event_dump(event); break; } } /* if machine == NULL */ return resp_machine;}static int is_wanted_resp_machine(void *a, void *b) { machine_pattern *pat; WTPRespMachine *m; m = a; pat = b; if (m->mid == pat->mid) return 1; if (pat->mid != -1) return 0; return m->tid == pat->tid && wap_addr_tuple_same(m->addr_tuple, pat->tuple);}static WTPRespMachine *resp_machine_find(WAPAddrTuple *tuple, long tid, long mid) { machine_pattern pat; WTPRespMachine *m; pat.tuple = tuple; pat.tid = tid; pat.mid = mid; m = list_search(resp_machines, &pat, is_wanted_resp_machine); return m;}static WTPRespMachine *resp_machine_create(WAPAddrTuple *tuple, long tid, long tcl) { WTPRespMachine *resp_machine; resp_machine = gw_malloc(sizeof(WTPRespMachine)); #define ENUM(name) resp_machine->name = LISTEN; #define EVENT(name) resp_machine->name = NULL; #define INTEGER(name) resp_machine->name = 0; #define TIMER(name) resp_machine->name = gwtimer_create(resp_queue); #define ADDRTUPLE(name) resp_machine->name = NULL; #define LIST(name) resp_machine->name = NULL; #define SARDATA(name) resp_machine->name = NULL; #define MACHINE(field) field #include "wtp_resp_machine.def" list_append(resp_machines, resp_machine); resp_machine->mid = counter_increase(resp_machine_id_counter); resp_machine->addr_tuple = wap_addr_tuple_duplicate(tuple); resp_machine->tid = tid; resp_machine->tcl = tcl; debug("wap.wtp", 0, "WTP: Created WTPRespMachine %p (%ld)", (void *) resp_machine, resp_machine->mid); return resp_machine;} /* * Destroys a WTPRespMachine. Assumes it is safe to do so. Assumes it has * already been deleted from the machines list. */static void resp_machine_destroy(void * p){ WTPRespMachine *resp_machine; resp_machine = p; debug("wap.wtp", 0, "WTP: Destroying WTPRespMachine %p (%ld)", (void *) resp_machine, resp_machine->mid); list_delete_equal(resp_machines, resp_machine); #define ENUM(name) resp_machine->name = LISTEN; #define EVENT(name) wap_event_destroy(resp_machine->name); #define INTEGER(name) resp_machine->name = 0; #define TIMER(name) gwtimer_destroy(resp_machine->name); #define ADDRTUPLE(name) wap_addr_tuple_destroy(resp_machine->name); #define LIST(name) list_destroy(resp_machine->name,sar_info_destroy); #define SARDATA(name) sardata_destroy(resp_machine->name); #define MACHINE(field) field #include "wtp_resp_machine.def" gw_free(resp_machine);}/* * Create a TR-Invoke.ind event. */static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data) { WAPEvent *event; event = wap_event_create(TR_Invoke_Ind); event->u.TR_Invoke_Ind.ack_type = sm->u_ack; event->u.TR_Invoke_Ind.user_data = octstr_duplicate(user_data); event->u.TR_Invoke_Ind.tcl = sm->tcl; event->u.TR_Invoke_Ind.addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple); event->u.TR_Invoke_Ind.handle = sm->mid; return event;}/* * Create a TR-Result.cnf event. */static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm) { WAPEvent *event; event = wap_event_create(TR_Result_Cnf); event->u.TR_Result_Cnf.addr_tuple = wap_addr_tuple_duplicate(sm->addr_tuple); event->u.TR_Result_Cnf.handle = sm->mid; return event;}/* * Creates TR-Abort.ind event from a responder state machine. In addition, set * the responder indication flag. */static WAPEvent *create_tr_abort_ind(WTPRespMachine *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 = RESPONDER_INDICATION; return event;}/* * Start acknowledgement interval timer. Multiply time with * resp_timer_freq. */static void start_timer_A(WTPRespMachine *machine) { WAPEvent *timer_event; timer_event = wap_event_create(TimerTO_A); timer_event->u.TimerTO_A.handle = machine->mid; gwtimer_start(machine->timer, L_A_WITH_USER_ACK * resp_timer_freq, timer_event);}/* * Start retry interval timer. Multiply time with resp_timer_freq. */static void start_timer_R(WTPRespMachine *machine) { WAPEvent *timer_event; timer_event = wap_event_create(TimerTO_R); timer_event->u.TimerTO_R.handle = machine->mid; gwtimer_start(machine->timer, L_R_WITH_USER_ACK * resp_timer_freq, timer_event);}/* * Start segmentation timeout interval timer. Multiply time with * resp_timer_freq. */static void start_timer_W(WTPRespMachine *machine){ WAPEvent *timer_event; timer_event = wap_event_create(TimerTO_W); timer_event->u.TimerTO_W.handle = machine->mid; gwtimer_start(machine->timer, W_WITH_USER_ACK * resp_timer_freq, timer_event);}static void send_abort(WTPRespMachine *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(WTPRespMachine *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(WTPRespMachine *machine, WAPEvent **event) { WAPEvent *e, *orig_event; int psn; orig_event = *event; if (orig_event->type == RcvInvoke) { if (!orig_event->u.RcvInvoke.ttr || !orig_event->u.RcvInvoke.gtr) { /* SAR */ /* Ericcson set TTR flag even if we have the only part */ if (orig_event->u.RcvInvoke.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.RcvInvoke.user_data, 0); if (orig_event->u.RcvInvoke.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 == RcvSegInvoke) { add_sar_transaction(machine, orig_event->u.RcvSegInvoke.user_data, orig_event->u.RcvSegInvoke.psn); if (orig_event->u.RcvSegInvoke.gtr == 1) { /* Need to acknowledge */ e = wtp_pack_sar_ack(ACKNOWLEDGEMENT, machine->tid, machine->addr_tuple, orig_event->u.RcvSegInvoke.psn); dispatch_to_wdp(e); } if (orig_event->u.RcvSegInvoke.ttr == 1) { /* Need to feed to WSP */ /* Create assembled event */ psn = orig_event->u.RcvSegInvoke.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(WTPRespMachine *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(WTPRespMachine *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.RcvInvoke.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_result(WTPRespMachine *resp_machine, WAPEvent *event) { WAPEvent *result; WTPSARData *sar; int psn; gw_assert(resp_machine->sar != NULL); sar = resp_machine->sar; sar->data = octstr_duplicate(event->u.TR_Result_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_result(): data len = %lu", octstr_len(sar->data)); for (psn = 0; !sar->tr; psn++) { result = wtp_pack_sar_result(resp_machine, psn); if (sar->tr) resp_machine->result = wap_event_duplicate(result); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn); dispatch_to_wdp(result); sar->lsegm = psn; } resp_machine->rid = 1;}static void continue_sar_result(WTPRespMachine *resp_machine, WAPEvent *event) { WAPEvent *result; WTPSARData *sar; int psn; gw_assert(resp_machine->sar != NULL && event->type == RcvAck); sar = resp_machine->sar; debug("wap.wtp", 0, "WTP: continue_sar_result(): lsegm=%d, nsegm=%d, csegm=%d", sar->lsegm, sar->nsegm, sar->csegm); start_timer_R(resp_machine); if (event->u.RcvAck.psn>sar->csegm) { sar->csegm = event->u.RcvAck.psn; } sar->tr = 0; wap_event_destroy(resp_machine->result); resp_machine->result = NULL; for (psn = sar->csegm + 1; !sar->tr; psn++) { result = wtp_pack_sar_result(resp_machine, psn); if (sar->tr) resp_machine->result = wap_event_duplicate(result); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u",psn); dispatch_to_wdp(result); sar->lsegm = psn; }}static void resend_sar_result(WTPRespMachine *resp_machine, WAPEvent *event){ WAPEvent *result; WTPSARData *sar; int psn, i; gw_assert(resp_machine->sar != NULL && event->type == RcvNegativeAck); sar = resp_machine->sar; debug("wap.wtp", 0, "WTP: resend_sar_result(): lsegm=%d, nsegm=%d, csegm=%d", sar->lsegm, sar->nsegm, sar->csegm); start_timer_R(resp_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) { result = wtp_pack_sar_result(resp_machine, psn); wtp_pack_set_rid(result, 1); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn); dispatch_to_wdp(result); } } } else { /* if we have to resend a whole group */ sar->tr = 0; for (psn = sar->csegm+1; !sar->tr; psn++) { result = wtp_pack_sar_result(resp_machine, psn); wtp_pack_set_rid(result, 1); debug("wap.wtp", 0, "WTP: dispath_to_wdp(): psn = %u", psn); dispatch_to_wdp(result); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -