📄 acc_mod.c
字号:
if (service_type != -1) vals[V_SIP_SESSION].v = service_type;#endif return 0;}static int child_init(int rank){#ifdef SQL_ACC if (acc_db_init()<0) return -1;#endif/* DIAMETER */#ifdef DIAM_ACC /* open TCP connection */ DBG(M_NAME": Initializing TCP connection\n"); sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==-1) { DBG(M_NAME": TCP connection not established\n"); return -1; } DBG(M_NAME": TCP connection established on sockfd=%d\n", sockfd); /* every child with its buffer */ rb = (rd_buf_t*)pkg_malloc(sizeof(rd_buf_t)); if(!rb) { DBG("acc: mod_child_init: no more free memory\n"); return -1; } rb->buf = 0;#endif return 0;}static void destroy(void){#ifdef SQL_ACC acc_db_close();#endif#ifdef DIAM_ACC close_tcp_connection(sockfd);#endif}static inline void acc_preparse_req(struct sip_msg *rq){ /* try to parse from for From-tag for accounted transactions; * don't be worried about parsing outcome -- if it failed, * we will report N/A */ parse_headers(rq, HDR_CALLID| HDR_FROM| HDR_TO, 0 ); parse_from_header(rq); if (strchr(log_fmt, 'p') || strchr(log_fmt, 'D')) { parse_orig_ruri(rq); }}/* prepare message and transaction context for later accounting */static void acc_onreq( struct cell* t, int type, struct tmcb_params *ps ){ int tmcb_types; if (is_acc_on(ps->req) || is_mc_on(ps->req)) { /* install addaitional handlers */ tmcb_types = /* report on completed transactions */ TMCB_RESPONSE_OUT | /* account e2e acks if configured to do so */ TMCB_E2EACK_IN | /* report on missed calls */ TMCB_ON_FAILURE_RO | /* get incoming replies ready for processing */ TMCB_RESPONSE_IN; if (tmb.register_tmcb( 0, t, tmcb_types, tmcb_func, 0 )<=0) { LOG(L_ERR,"ERROR:acc:acc_onreq: cannot register additional " "callbacks\n"); return; } /* do some parsing in advance */ acc_preparse_req(ps->req); /* also, if that is INVITE, disallow silent t-drop */ if (ps->req->REQ_METHOD==METHOD_INVITE) { DBG("DEBUG: noisy_timer set for accounting\n"); t->flags |= T_NOISY_CTIMER_FLAG; } }}/* is this reply of interest for accounting ? */static inline int should_acc_reply(struct cell *t, int code){ struct sip_msg *r; r=t->uas.request; /* validation */ if (r==0) { LOG(L_ERR, "ERROR: acc: should_acc_reply: 0 request\n"); return 0; } /* negative transactions reported otherwise only if explicitly * demanded */ if (!failed_transactions && code >=300) return 0; if (!is_acc_on(r)) return 0; if (skip_cancel(r)) return 0; if (code < 200 && ! (early_media && code==183)) return 0; return 1; /* seed is through, we will account this reply */}/* parse incoming replies before cloning */static inline void acc_onreply_in(struct cell *t, struct sip_msg *reply, int code, void *param){ /* validation */ if (t->uas.request==0) { LOG(L_ERR, "ERROR: acc: should_acc_reply: 0 request\n"); return; } /* don't parse replies in which we are not interested */ /* missed calls enabled ? */ if (((is_invite(t) && code>=300 && is_mc_on(t->uas.request)) || should_acc_reply(t,code)) && (reply && reply!=FAKED_REPLY)) { parse_headers(reply, HDR_TO, 0 ); }}/* initiate a report if we previously enabled MC accounting for this t */static inline void on_missed(struct cell *t, struct sip_msg *reply, int code, void *param ){ int reset_lmf; #ifdef SQL_ACC int reset_dmf;#endif#ifdef RAD_ACC int reset_rmf;#endif/* DIAMETER */#ifdef DIAM_ACC int reset_dimf;#endif /* validation */ if (t->uas.request==0) { DBG("DBG: acc: on_missed: no uas.request, local t; skipping\n"); return; } if (is_invite(t) && code>=300) { if (is_log_mc_on(t->uas.request)) { acc_log_missed( t, reply, code); reset_lmf=1; } else reset_lmf=0;#ifdef SQL_ACC if (is_db_mc_on(t->uas.request)) { acc_db_missed( t, reply, code); reset_dmf=1; } else reset_dmf=0;#endif#ifdef RAD_ACC if (is_rad_mc_on(t->uas.request)) { acc_rad_missed(t, reply, code ); reset_rmf=1; } else reset_rmf=0;#endif/* DIAMETER */#ifdef DIAM_ACC if (is_diam_mc_on(t->uas.request)) { acc_diam_missed(t, reply, code ); reset_dimf=1; } else reset_dimf=0;#endif /* we report on missed calls when the first * forwarding attempt fails; we do not wish to * report on every attempt; so we clear the flags; * we do it after all reporting is over to be sure * that all reporting functions got a fair chance */ if (reset_lmf) resetflag(t->uas.request, log_missed_flag);#ifdef SQL_ACC if (reset_dmf) resetflag(t->uas.request, db_missed_flag);#endif#ifdef RAD_ACC if (reset_rmf) resetflag(t->uas.request, radius_missed_flag);#endif/* DIAMETER */ #ifdef DIAM_ACC if (reset_dimf) resetflag(t->uas.request, diameter_missed_flag);#endif }}/* initiate a report if we previously enabled accounting for this t */static inline void acc_onreply( struct cell* t, struct sip_msg *reply, int code, void *param ){ /* validation */ if (t->uas.request==0) { DBG("DBG: acc: onreply: no uas.request, local t; skipping\n"); return; } /* acc_onreply is bound to TMCB_REPLY which may be called from _reply, like when FR hits; we should not miss this event for missed calls either */ on_missed(t, reply, code, param ); if (!should_acc_reply(t, code)) return; if (is_log_acc_on(t->uas.request)) acc_log_reply(t, reply, code);#ifdef SQL_ACC if (is_db_acc_on(t->uas.request)) acc_db_reply(t, reply, code);#endif#ifdef RAD_ACC if (is_rad_acc_on(t->uas.request)) acc_rad_reply(t, reply, code);#endif/* DIAMETER */#ifdef DIAM_ACC if (is_diam_acc_on(t->uas.request)) acc_diam_reply(t, reply, code);#endif}static inline void acc_onack( struct cell* t , struct sip_msg *ack, int code, void *param ){ /* only for those guys who insist on seeing ACKs as well */ if (!report_ack) return; /* if acc enabled for flagged transaction, check if flag matches */ if (is_log_acc_on(t->uas.request)) { acc_preparse_req(ack); acc_log_ack(t, ack); }#ifdef SQL_ACC if (is_db_acc_on(t->uas.request)) { acc_preparse_req(ack); acc_db_ack(t, ack); }#endif#ifdef RAD_ACC if (is_rad_acc_on(t->uas.request)) { acc_preparse_req(ack); acc_rad_ack(t,ack); }#endif/* DIAMETER */#ifdef DIAM_ACC if (is_diam_acc_on(t->uas.request)) { acc_preparse_req(ack); acc_diam_ack(t,ack); }#endif }static void tmcb_func( struct cell* t, int type, struct tmcb_params *ps ){ if (type&TMCB_RESPONSE_OUT) { acc_onreply( t, ps->rpl, ps->code, ps->param ); } else if (type&TMCB_E2EACK_IN) { acc_onack( t, ps->req, ps->code, ps->param ); } else if (type&TMCB_ON_FAILURE_RO) { on_missed( t, ps->rpl, ps->code, ps->param ); } else if (type&TMCB_RESPONSE_IN) { acc_onreply_in( t, ps->rpl, ps->code, ps->param); }}/* these wrappers parse all what may be needed; they don't care about * the result -- accounting functions just display "unavailable" if there * is nothing meaningful */static int w_acc_log_request(struct sip_msg *rq, char *comment, char *foo){ str txt; str phrase; txt.s=ACC_REQUEST; txt.len=ACC_REQUEST_LEN; phrase.s=comment; phrase.len=strlen(comment); /* fix_param would be faster! */ acc_preparse_req(rq); return acc_log_request(rq, rq->to, &txt, &phrase);}#ifdef SQL_ACCstatic int w_acc_db_request(struct sip_msg *rq, char *comment, char *table){ str phrase; phrase.s=comment; phrase.len=strlen(comment); /* fix_param would be faster! */ acc_preparse_req(rq); return acc_db_request(rq, rq->to,&phrase,table, SQL_MC_FMT );}#endif#ifdef RAD_ACCstatic int w_acc_rad_request(struct sip_msg *rq, char *comment, char *foo){ str phrase; phrase.s=comment; phrase.len=strlen(comment); /* fix_param would be faster! */ acc_preparse_req(rq); return acc_rad_request(rq, rq->to,&phrase);}#endif/* DIAMETER */#ifdef DIAM_ACCstatic int w_acc_diam_request(struct sip_msg *rq, char *comment, char *foo){ str phrase; phrase.s=comment; phrase.len=strlen(comment); /* fix_param would be faster! */ acc_preparse_req(rq); return acc_diam_request(rq, rq->to,&phrase);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -