⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wtp_init.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 int is_wanted_init_machine(void *a, void *b) {    struct machine_pattern *pat;    WTPInitMachine *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 WTPInitMachine *init_machine_find(WAPAddrTuple *tuple, long tid,                                          long mid) {    struct machine_pattern pat;    WTPInitMachine *m;	    pat.tuple = tuple;    pat.tid = tid;    pat.mid = mid;	    m = list_search(init_machines, &pat, is_wanted_init_machine);    return m;}/* * 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_A.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;}/* * 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 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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -