/* prepare message and transaction context for later accounting */ void acc_onreq( struct cell* t, int type, struct tmcb_params *ps ) { int tmcb_types; int is_invite; if ( ps->req && !skip_cancel(ps->req) && ( is_acc_on(ps->req) || is_mc_on(ps->req) || is_acc_prepare_on(ps->req) ) ) { /* do some parsing in advance */ if (acc_preparse_req(ps->req)<0) return; is_invite = (ps->req->REQ_METHOD==METHOD_INVITE)?1:0; /* install additional handlers */ tmcb_types = /* report on completed transactions */ TMCB_RESPONSE_OUT | /* account e2e acks if configured to do so */ ((report_ack && is_acc_on(ps->req))?TMCB_E2EACK_IN:0) | /* get incoming replies ready for processing */ TMCB_RESPONSE_IN | /* report on missed calls */ ((is_invite && (is_mc_on(ps->req) || is_acc_prepare_on(ps->req)))?TMCB_ON_FAILURE:0); if (tmb.register_tmcb( 0, t, tmcb_types, tmcb_func, 0, 0 )<=0) { LM_ERR("cannot register additional callbacks\n"); return; } /* if required, determine request direction */ if( detect_direction && !rrb.is_direction(ps->req,RR_FLOW_UPSTREAM) ) { LM_DBG("detected an UPSTREAM req -> flaging it\n"); ps->req->msg_flags |= FL_REQ_UPSTREAM; } } }
int w_acc_db_request(struct sip_msg *rq, pv_elem_t* comment, char *table) { struct acc_param accp; int table_len; if (!table) { LM_ERR("db support not configured\n"); return -1; } if (acc_preparse_req(rq)<0) return -1; table_len = strlen(table); acc_pvel_to_acc_param(rq, comment, &accp); env_set_to( rq->to ); env_set_comment( &accp ); env_set_text(table, table_len); if (table_len == db_table_mc.len && (strncmp(table, db_table_mc.s, table_len) == 0)) { return acc_db_request(rq, NULL, &mc_ins_list, 0); } if (table_len == db_table_acc.len && (strncmp(table, db_table_acc.s, table_len) == 0)) { return acc_db_request(rq, NULL, &acc_ins_list, 0); } return acc_db_request( rq, NULL,NULL, 0); }
int w_acc_evi_request(struct sip_msg *rq, pv_elem_t* comment, char *foo) { struct acc_param accp; if (acc_preparse_req(rq)<0) return -1; acc_pvel_to_acc_param(rq, comment, &accp); env_set_to( rq->to ); env_set_comment( &accp ); if (is_cdr_acc_on(rq) && is_evi_acc_on(rq)) { env_set_event(acc_cdr_event); } else if (is_evi_acc_on(rq) && acc_env.code < 300) { env_set_event(acc_event); } else if (is_evi_mc_on(rq)) { env_set_event(acc_missed_event); } else { LM_WARN("evi request flags not set\n"); return 1; } return acc_evi_request( rq, NULL, 0); }
static inline void acc_onack( struct cell* t, struct sip_msg *req, struct sip_msg *ack, int code) { if (acc_preparse_req(ack)<0) return; /* set env variables */ env_set_to( ack->to?ack->to:req->to ); env_set_code_status( t->uas.status, 0 ); if (is_log_acc_on(req)) { env_set_text( ACC_ACKED, ACC_ACKED_LEN); acc_log_request( ack ); } #ifdef SQL_ACC if (is_db_acc_on(req)) { if(acc_db_set_table_name(ack, db_table_acc_data, &db_table_acc)<0) { LM_ERR("cannot set acc db table name\n"); return; } acc_db_request( ack ); } #endif /* DIAMETER */ #ifdef DIAM_ACC if (is_diam_acc_on(req)) { acc_diam_request(ack); } #endif /* run extra acc engines */ acc_run_engines(ack, 0, NULL); }
int w_acc_diam_request(struct sip_msg *rq, char *comment, char *foo) { if (acc_preparse_req(rq)<0) return -1; env_set_to( rq->to ); env_set_comment((struct acc_param*)comment); return acc_diam_request( rq, NULL); }
static 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 ); }
int w_acc_log_request(struct sip_msg *rq, char *comment, char *foo) { if (acc_preparse_req(rq)<0) return -1; env_set_to( rq->to ); env_set_comment((struct acc_param*)comment); env_set_text( ACC_REQUEST, ACC_REQUEST_LEN); return acc_log_request( rq, NULL); }
static 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); }
int w_acc_diam_request(struct sip_msg *rq, char *comment, char *foo) { struct acc_param *param = (struct acc_param*)comment; if (acc_preparse_req(rq)<0) return -1; if(acc_get_param_value(rq, param)<0) return -1; env_set_to( rq->to ); env_set_comment(param); return acc_diam_request(rq); }
/* 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); }
int w_acc_aaa_request(struct sip_msg *rq, char *comment, char* foo) { if (!aaa_proto_url) { LM_ERR("aaa support not configured\n"); return -1; } if (acc_preparse_req(rq)<0) return -1; env_set_to( rq->to ); env_set_comment((struct acc_param*)comment); return acc_aaa_request( rq, NULL); }
/* prepare message and transaction context for later accounting */ static void acc_onreq( struct cell* t, struct sip_msg *msg, int code, void *param ) { if (is_acc_on(msg) || is_mc_on(msg)) { acc_preparse_req(msg); /* also, if that is INVITE, disallow silent t-drop */ if (msg->REQ_METHOD==METHOD_INVITE) { DBG("DEBUG: noisy_timer set for accounting\n"); t->noisy_ctimer=1; } } }
int w_acc_diam_request(struct sip_msg *rq, pv_elem_t* comment, char *foo) { struct acc_param accp; if (acc_preparse_req(rq)<0) return -1; acc_pvel_to_acc_param(rq, comment, &accp); env_set_to( rq->to ); env_set_comment( &accp ); return acc_diam_request( rq, NULL); }
/** * @brief execute an acc event via a specific engine */ int acc_api_exec(struct sip_msg *rq, acc_engine_t *eng, acc_param_t* comment) { acc_info_t inf; if (acc_preparse_req(rq)<0) return -1; env_set_to(rq->to); env_set_comment(comment); memset(&inf, 0, sizeof(acc_info_t)); inf.env = &acc_env; acc_api_set_arrays(&inf); return eng->acc_req(rq, &inf); }
int w_acc_db_request(struct sip_msg *rq, char *comment, char *table) { if (!table) { LM_ERR("db support not configured\n"); return -1; } if (acc_preparse_req(rq)<0) return -1; env_set_to( rq->to ); env_set_comment((struct acc_param*)comment); env_set_text(table, strlen(table)); return acc_db_request( rq, NULL,NULL); }
int w_acc_log_request(struct sip_msg *rq, pv_elem_t* comment, char *foo) { struct acc_param accp; if (acc_preparse_req(rq)<0) return -1; acc_pvel_to_acc_param(rq, comment, &accp); env_set_to( rq->to ); env_set_comment( &accp ); env_set_text( ACC_REQUEST, ACC_REQUEST_LEN); return acc_log_request( rq, NULL, 0); }
static 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 }
/* prepare message and transaction context for later accounting */ void acc_onreq( struct cell* t, int type, struct tmcb_params *ps ) { int tmcb_types; int is_invite; int_str _avp_created_value; if ( ps->req && !skip_cancel(ps->req) && (is_acc_on(ps->req) || is_mc_on(ps->req)) ) { /* do some parsing in advance */ if (acc_preparse_req(ps->req)<0) return; is_invite = (ps->req->REQ_METHOD==METHOD_INVITE)?1:0; /* install additional handlers */ tmcb_types = /* report on completed transactions */ TMCB_RESPONSE_OUT | /* get incoming replies ready for processing */ TMCB_RESPONSE_IN | /* report on missed calls */ ((is_invite && is_mc_on(ps->req))?TMCB_ON_FAILURE:0) ; /* if cdr accounting is enabled */ if (is_cdr_acc_on(ps->req) && !has_totag(ps->req)) { _avp_created_value.n = time(NULL); if ( add_avp(0, acc_created_avp_id, _avp_created_value) != 0) { LM_ERR("failed to add created avp value!\n"); return; } if (is_invite && create_acc_dlg(ps->req) < 0) { LM_ERR("cannot use dialog accounting module\n"); return; } } if (tmb.register_tmcb( 0, t, tmcb_types, tmcb_func, 0, 0 )<=0) { LM_ERR("cannot register additional callbacks\n"); return; } /* if required, determine request direction */ if( detect_direction && !rrb.is_direction(ps->req,RR_FLOW_UPSTREAM) ) { LM_DBG("detected an UPSTREAM req -> flaging it\n"); ps->req->msg_flags |= FL_REQ_UPSTREAM; } } }
int w_acc_aaa_request(struct sip_msg *rq, pv_elem_t* comment, char* foo) { struct acc_param accp; if (!aaa_proto_url) { LM_ERR("aaa support not configured\n"); return -1; } if (acc_preparse_req(rq)<0) return -1; acc_pvel_to_acc_param(rq, comment, &accp); env_set_to( rq->to ); env_set_comment( &accp ); return acc_aaa_request( rq, NULL, 0); }
int w_acc_db_request(struct sip_msg *rq, char *comment, char *table) { struct acc_param *param = (struct acc_param*)comment; if (!table) { LM_ERR("db support not configured\n"); return -1; } if (acc_preparse_req(rq)<0) return -1; if(acc_db_set_table_name(rq, (void*)table, NULL)<0) { LM_ERR("cannot set table name\n"); return -1; } if(acc_get_param_value(rq, param)<0) return -1; env_set_to( rq->to ); env_set_comment(param); return acc_db_request(rq); }
int w_do_acc_3(struct sip_msg* msg, char* type_p, char* flags_p, char* table_p) { unsigned long long type=0, flags=0; unsigned long long flag_mask; acc_ctx_t* acc_ctx; acc_type_param_t* acc_param; str in; str table_name; int tmcb_types; int is_invite; if (type_p == NULL) { LM_ERR("accounting type is mandatory!\n"); return -1; } acc_param = (acc_type_param_t *)type_p; if (acc_param->t == DO_ACC_PARAM_TYPE_VALUE) { type = acc_param->u.ival; } else { if (pv_printf_s(msg, acc_param->u.pval, &in) < 0) { LM_ERR("failed to fetch type value!\n"); return -1; } if ((type=do_acc_parse(&in, do_acc_type_parser)) == DO_ACC_ERR) { LM_ERR("Invalid expression <%.*s> for acc type!\n", in.len, in.s); return -1; } } if (table_p != NULL) { if (fixup_get_svalue(msg, (gparam_p)table_p, &table_name) < 0) { LM_ERR("failed to fetch table name!\n"); return -1; } } if (flags_p != NULL) { flags= *(unsigned long long*)flags_p; } flag_mask = type + type * flags; if (is_cdr_acc_on(flag_mask)) { /* setting this flag will allow us to register everything * that is needed for CDR accounting only once */ set_cdr_values_registered(flag_mask); } /* is it the first time when the function was called ? */ acc_ctx = try_fetch_ctx(); /* we go in here only if do_accounting function was called before; * if accounting context is null or it's created but flags value is * 0(meaning that context was created from somewhere else but do_accounting * wasn't called) then we need to jump over this and register * all the callbacks we need */ if (acc_ctx != NULL && acc_ctx->flags != 0) { /* do_accounting already called once */ /* first check if the accounting table changed */ if (is_db_acc_on(flag_mask) && (table_p != NULL || (acc_ctx->acc_table.s==NULL && acc_ctx->acc_table.len == 0))) { if (table_p == NULL) { table_name = db_table_acc; } if (store_acc_table( acc_ctx, &table_name) < 0) { LM_ERR("failed to store acc table!\n"); return -1; } } if (!cdr_values_registered(acc_ctx->flags) && cdr_values_registered(flag_mask)) { /* CDR support requested for the first time, we need to create * the dialog support, if an initial INVITE */ if (!has_totag(msg)) { acc_ctx->created = time(NULL); if (msg->REQ_METHOD == METHOD_INVITE && create_acc_dlg(msg) < 0) { LM_ERR("cannot use dialog accounting module\n"); return -1; } } } /* if it's the first time the missed calls flag was used register the callback */ if (is_mc_acc_on(flag_mask) && !failure_cb_registered(acc_ctx->flags)) { if (tmb.register_tmcb( msg, 0, TMCB_ON_FAILURE, tmcb_func, acc_ctx, 0)<=0) { LM_ERR("cannot register missed calls callback\n"); return -1; } /* don't allow the callback to be registered agian in the future */ set_failure_cb_registered(acc_ctx->flags); } acc_ctx->flags |= flag_mask; return 1; } /* initialize accounting context if not created before */ if (acc_ctx == NULL && init_acc_ctx(&acc_ctx) < 0) { LM_ERR("failed to create accounting context!\n"); return -1; } /* move acc table in context if we have database accounting */ if (is_db_acc_on(flag_mask)) { if (table_p == NULL) { table_name = db_table_acc; } if (store_acc_table( acc_ctx, &table_name) < 0) { LM_ERR("failed to store acc table!\n"); return -1; } } /* * the first bit in each byte will just tell that we want that type of * accounting * next bits will tell extra options for that type of accounting * so we keep the first bits in each byte and on the following positions * next flags */ acc_ctx->flags = flag_mask; /* make sure that context won't be freed by GLOBAL_CONTEXT free function */ acc_ctx->flags |= ACC_PROCESSING_CTX_NO_FREE; ACC_PUT_CTX(acc_ctx); if ( msg && !skip_cancel(msg) && (is_acc_on(acc_ctx->flags) || is_mc_acc_on(acc_ctx->flags)) ) { /* do some parsing in advance */ if (acc_preparse_req(msg)<0) return -1; is_invite = (msg->REQ_METHOD==METHOD_INVITE)?1:0; /* install additional handlers */ tmcb_types = /* report on completed transactions */ TMCB_RESPONSE_IN; if (is_invite && is_mc_acc_on(acc_ctx->flags)) { /* register it manually; see explanation below * get incoming replies ready for processing */ /* TMCB_RESPONSE_OUT | */ /* report on missed calls */ tmcb_types |= TMCB_ON_FAILURE; /* the flag will help on further do_accounting calls to know * not to register the callback twice */ set_failure_cb_registered(acc_ctx->flags); } /* if cdr accounting is enabled */ if (is_cdr_acc_on(acc_ctx->flags) && !has_totag(msg)) { acc_ctx->created = time(NULL); if (is_invite && create_acc_dlg(msg) < 0) { LM_ERR("cannot use dialog accounting module\n"); return -1; } } /* we do register_tmcb twice because we want to register the free * function only once */ if (tmb.register_tmcb( msg, 0, TMCB_RESPONSE_OUT, tmcb_func, acc_ctx, tm_free_acc_ctx)<=0) { LM_ERR("cannot register additional callbacks\n"); return -1; } if (tmb.register_tmcb( msg, 0, tmcb_types, tmcb_func, acc_ctx, 0)<=0) { LM_ERR("cannot register additional callbacks\n"); return -1; } /* if required, determine request direction */ if( detect_direction && !rrb.is_direction(msg,RR_FLOW_UPSTREAM) ) { LM_DBG("detected an UPSTREAM req -> flaging it\n"); msg->msg_flags |= FL_REQ_UPSTREAM; } } return 1; }
int w_do_acc_3(struct sip_msg* msg, char* type_p, char* flags_p, char* table_p) { unsigned long long type=0, flags=0; unsigned long long *flag_mask_p, flag_mask; acc_type_param_t* acc_param; str in; str table_name; int tmcb_types; int is_invite; int_str _avp_created_value; if (type_p == NULL) { LM_ERR("accounting type is mandatory!\n"); return -1; } acc_param = (acc_type_param_t *)type_p; if (acc_param->t == DO_ACC_PARAM_TYPE_VALUE) { type = acc_param->u.ival; } else { if (pv_printf_s(msg, acc_param->u.pval, &in) < 0) { LM_ERR("failed to fetch type value!\n"); return -1; } if ((type=do_acc_parse(&in, do_acc_type_parser)) < 0) { LM_ERR("Invalid expression <%.*s> for acc type!\n", in.len, in.s); return -1; } } if (flags_p != NULL) { flags= *(unsigned long long*)flags_p; } flag_mask = type + type * flags; if (is_cdr_acc_on(flag_mask)) { /* setting this flag will allow us to register everything * that is needed for CDR accounting only once */ set_cdr_values_registered(flag_mask); } /* is it the first time when the function was called ? */ if ((flag_mask_p=try_fetch_flags()) != NULL) { /* no the first time ; check now if CDRs are requested now * for the first time */ if (!cdr_values_registered(*flag_mask_p) && cdr_values_registered(flag_mask)) { /* CDR support requested for the first time, we need to create * the dialog support, if an initial INVITE */ if (!has_totag(msg)) { _avp_created_value.n = time(NULL); if ( add_avp(0, acc_created_avp_id, _avp_created_value) != 0) { LM_ERR("failed to add created avp value!\n"); return -1; } if (msg->REQ_METHOD == METHOD_INVITE && create_acc_dlg(msg) < 0) { LM_ERR("cannot use dialog accounting module\n"); return -1; } } } *flag_mask_p |= flag_mask; return 1; } /* setting accouting for the first time, allocate the flags holder */ flag_mask_p=shm_malloc(sizeof(unsigned long long)); if (flag_mask_p==NULL) { LM_ERR("No more shm mem!\n"); return -1; } /* * the first bit in each byte will just tell that we want that type of * accounting * next bits will tell extra options for that type of accounting * so we keep the first bits in each byte and on the following positions * next flags */ *flag_mask_p = flag_mask; ACC_PUT_FLAGS(flag_mask_p); if (table_p != NULL) { if (fixup_get_svalue(msg, (gparam_p)table_p, &table_name) < 0) { LM_ERR("failed to fetch table name!\n"); return -1; } } if ( msg && !skip_cancel(msg) && (is_acc_on(*flag_mask_p) || is_mc_acc_on(*flag_mask_p)) ) { /* do some parsing in advance */ if (acc_preparse_req(msg)<0) return -1; is_invite = (msg->REQ_METHOD==METHOD_INVITE)?1:0; /* install additional handlers */ tmcb_types = /* report on completed transactions */ TMCB_RESPONSE_IN | /* register it manually; see explanation below * get incoming replies ready for processing */ /* TMCB_RESPONSE_OUT | */ /* report on missed calls */ ((is_invite && is_mc_acc_on(*flag_mask_p))?TMCB_ON_FAILURE:0) ; /* if cdr accounting is enabled */ if (is_cdr_acc_on(*flag_mask_p) && !has_totag(msg)) { _avp_created_value.n = time(NULL); if ( add_avp(0, acc_created_avp_id, _avp_created_value) != 0) { LM_ERR("failed to add created avp value!\n"); return -1; } if (is_invite && create_acc_dlg(msg) < 0) { LM_ERR("cannot use dialog accounting module\n"); return -1; } } /* we do register_tmcb twice because we wan't to register the free * fucntion only once */ if (tmb.register_tmcb( msg, 0, TMCB_RESPONSE_OUT, tmcb_func, flag_mask_p, tm_free_acc_mask)<=0) { LM_ERR("cannot register additional callbacks\n"); return -1; } if (tmb.register_tmcb( msg, 0, tmcb_types, tmcb_func, flag_mask_p, 0)<=0) { LM_ERR("cannot register additional callbacks\n"); return -1; } /* if required, determine request direction */ if( detect_direction && !rrb.is_direction(msg,RR_FLOW_UPSTREAM) ) { LM_DBG("detected an UPSTREAM req -> flaging it\n"); msg->msg_flags |= FL_REQ_UPSTREAM; } } return 1; }