00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00038 #include <stdio.h>
00039 #include <string.h>
00040
00041 #include "../../dprint.h"
00042 #include "../../parser/parse_from.h"
00043 #include "../../parser/parse_content.h"
00044 #include "../../modules/tm/tm_load.h"
00045 #include "../rr/api.h"
00046 #include "../../flags.h"
00047 #include "acc.h"
00048 #include "acc_api.h"
00049 #include "acc_mod.h"
00050 #include "acc_logic.h"
00051
00052 extern struct tm_binds tmb;
00053 extern struct rr_binds rrb;
00054
00055 struct acc_enviroment acc_env;
00056
00057
00058 #define is_acc_flag_set(_rq,_flag) (((_flag) != -1) && (isflagset((_rq), (_flag)) == 1))
00059 #define reset_acc_flag(_rq,_flag) (resetflag((_rq), (_flag)))
00060
00061 #define is_failed_acc_on(_rq) is_acc_flag_set(_rq,failed_transaction_flag)
00062
00063 #define is_log_acc_on(_rq) is_acc_flag_set(_rq,log_flag)
00064 #define is_log_mc_on(_rq) is_acc_flag_set(_rq,log_missed_flag)
00065
00066 #ifdef SQL_ACC
00067 #define is_db_acc_on(_rq) is_acc_flag_set(_rq,db_flag)
00068 #define is_db_mc_on(_rq) is_acc_flag_set(_rq,db_missed_flag)
00069 #else
00070 #define is_db_acc_on(_rq) (0)
00071 #define is_db_mc_on(_rq) (0)
00072 #endif
00073
00074 #ifdef RAD_ACC
00075 #define is_rad_acc_on(_rq) is_acc_flag_set(_rq,radius_flag)
00076 #define is_rad_mc_on(_rq) is_acc_flag_set(_rq,radius_missed_flag)
00077 #else
00078 #define is_rad_acc_on(_rq) (0)
00079 #define is_rad_mc_on(_rq) (0)
00080 #endif
00081
00082
00083 #ifdef DIAM_ACC
00084 #define is_diam_acc_on(_rq) is_acc_flag_set(_rq,diameter_flag)
00085 #define is_diam_mc_on(_rq) is_acc_flag_set(_rq,diameter_missed_flag)
00086 #else
00087 #define is_diam_acc_on(_rq) (0)
00088 #define is_diam_mc_on(_rq) (0)
00089 #endif
00090
00091 #define is_acc_on(_rq) \
00092 ( (is_log_acc_on(_rq)) || (is_db_acc_on(_rq)) \
00093 || (is_rad_acc_on(_rq)) || (is_diam_acc_on(_rq)) )
00094
00095 #define is_mc_on(_rq) \
00096 ( (is_log_mc_on(_rq)) || (is_db_mc_on(_rq)) \
00097 || (is_rad_mc_on(_rq)) || (is_diam_mc_on(_rq)) )
00098
00099 #define skip_cancel(_rq) \
00100 (((_rq)->REQ_METHOD==METHOD_CANCEL) && report_cancels==0)
00101
00102 #define is_acc_prepare_on(_rq) \
00103 (is_acc_flag_set(_rq,acc_prepare_flag))
00104
00105
00106
00107 static void tmcb_func( struct cell* t, int type, struct tmcb_params *ps );
00108
00109
00110 static inline struct hdr_field* get_rpl_to( struct cell *t,
00111 struct sip_msg *reply)
00112 {
00113 if (reply==FAKED_REPLY || !reply || !reply->to)
00114 return t->uas.request->to;
00115 else
00116 return reply->to;
00117 }
00118
00119
00120 static inline void env_set_to(struct hdr_field *to)
00121 {
00122 acc_env.to = to;
00123 }
00124
00125
00126 static inline void env_set_text(char *p, int len)
00127 {
00128 acc_env.text.s = p;
00129 acc_env.text.len = len;
00130 }
00131
00132
00133 static inline void env_set_code_status( int code, struct sip_msg *reply)
00134 {
00135 static char code_buf[INT2STR_MAX_LEN];
00136
00137 acc_env.code = code;
00138 if (reply==FAKED_REPLY || reply==NULL) {
00139
00140 acc_env.code_s.s =
00141 int2bstr((unsigned long)code, code_buf, &acc_env.code_s.len);
00142
00143 acc_env.reason.s = error_text(code);
00144 acc_env.reason.len = strlen(acc_env.reason.s);
00145 } else {
00146 acc_env.code_s = reply->first_line.u.reply.status;
00147 acc_env.reason = reply->first_line.u.reply.reason;
00148 }
00149 }
00150
00151
00152 static inline void env_set_comment(struct acc_param *accp)
00153 {
00154 acc_env.code = accp->code;
00155 acc_env.code_s = accp->code_s;
00156 acc_env.reason = accp->reason;
00157 }
00158
00159
00160 static inline int acc_preparse_req(struct sip_msg *req)
00161 {
00162 if ( (parse_headers(req,HDR_CALLID_F|HDR_CSEQ_F|HDR_FROM_F|HDR_TO_F,0)<0)
00163 || (parse_from_header(req)<0 ) ) {
00164 LM_ERR("failed to preparse request\n");
00165 return -1;
00166 }
00167 return 0;
00168 }
00169
00170
00171
00172 int w_acc_log_request(struct sip_msg *rq, char *comment, char *foo)
00173 {
00174 if (acc_preparse_req(rq)<0)
00175 return -1;
00176 env_set_to( rq->to );
00177 env_set_comment((struct acc_param*)comment);
00178 env_set_text( ACC_REQUEST, ACC_REQUEST_LEN);
00179 return acc_log_request(rq);
00180 }
00181
00182
00183 #ifdef SQL_ACC
00184 int w_acc_db_request(struct sip_msg *rq, char *comment, char *table)
00185 {
00186 if (!table) {
00187 LM_ERR("db support not configured\n");
00188 return -1;
00189 }
00190 if (acc_preparse_req(rq)<0)
00191 return -1;
00192 env_set_to( rq->to );
00193 env_set_comment((struct acc_param*)comment);
00194 env_set_text(table, strlen(table));
00195 return acc_db_request(rq);
00196 }
00197 #endif
00198
00199
00200 #ifdef RAD_ACC
00201 int w_acc_rad_request(struct sip_msg *rq, char *comment, char *foo)
00202 {
00203 if (acc_preparse_req(rq)<0)
00204 return -1;
00205 env_set_to( rq->to );
00206 env_set_comment((struct acc_param*)comment);
00207 return acc_rad_request(rq);
00208 }
00209 #endif
00210
00211
00212 #ifdef DIAM_ACC
00213 int w_acc_diam_request(struct sip_msg *rq, char *comment, char *foo)
00214 {
00215 if (acc_preparse_req(rq)<0)
00216 return -1;
00217 env_set_to( rq->to );
00218 env_set_comment((struct acc_param*)comment);
00219 return acc_diam_request(rq);
00220 }
00221 #endif
00222
00223
00224
00225
00226 void acc_onreq( struct cell* t, int type, struct tmcb_params *ps )
00227 {
00228 int tmcb_types;
00229 int is_invite;
00230
00231 if ( ps->req && !skip_cancel(ps->req) &&
00232 ( is_acc_on(ps->req) || is_mc_on(ps->req)
00233 || is_acc_prepare_on(ps->req) ) ) {
00234
00235 if (acc_preparse_req(ps->req)<0)
00236 return;
00237 is_invite = (ps->req->REQ_METHOD==METHOD_INVITE)?1:0;
00238
00239 tmcb_types =
00240
00241 TMCB_RESPONSE_OUT |
00242
00243 ((report_ack && is_acc_on(ps->req))?TMCB_E2EACK_IN:0) |
00244
00245 TMCB_RESPONSE_IN |
00246
00247 ((is_invite && (is_mc_on(ps->req)
00248 || is_acc_prepare_on(ps->req)))?TMCB_ON_FAILURE:0);
00249 if (tmb.register_tmcb( 0, t, tmcb_types, tmcb_func, 0, 0 )<=0) {
00250 LM_ERR("cannot register additional callbacks\n");
00251 return;
00252 }
00253
00254 if( detect_direction && !rrb.is_direction(ps->req,RR_FLOW_UPSTREAM) ) {
00255 LM_DBG("detected an UPSTREAM req -> flaging it\n");
00256 ps->req->msg_flags |= FL_REQ_UPSTREAM;
00257 }
00258 }
00259 }
00260
00261
00262
00263
00264 static inline int should_acc_reply(struct sip_msg *req, struct sip_msg *rpl,
00265 int code)
00266 {
00267 unsigned int i;
00268
00269
00270
00271
00272 if (code >= 300) {
00273 if (!is_failed_acc_on(req)) return 0;
00274 i = 0;
00275 while (failed_filter[i] != 0) {
00276 if (failed_filter[i] == code) return 0;
00277 i++;
00278 }
00279 return 1;
00280 }
00281
00282 if ( !is_acc_on(req) )
00283 return 0;
00284
00285 if ( code<200 && !(early_media &&
00286 parse_headers(rpl,HDR_CONTENTLENGTH_F, 0) == 0 &&
00287 rpl->content_length && get_content_length(rpl) > 0))
00288 return 0;
00289
00290 return 1;
00291 }
00292
00293
00294
00295
00296 static inline void acc_onreply_in(struct cell *t, struct sip_msg *req,
00297 struct sip_msg *reply, int code)
00298 {
00299
00300
00301 if ( (reply && reply!=FAKED_REPLY) && (should_acc_reply(req,reply,code)
00302 || (is_invite(t) && code>=300 && is_mc_on(req))) ) {
00303 parse_headers(reply, HDR_TO_F, 0 );
00304 }
00305 }
00306
00307
00308
00309
00310 static inline void on_missed(struct cell *t, struct sip_msg *req,
00311 struct sip_msg *reply, int code)
00312 {
00313 str new_uri_bk = {0, 0};
00314 int flags_to_reset = 0;
00315
00316
00317 if (t->relayed_reply_branch>=0) {
00318 new_uri_bk = req->new_uri;
00319 req->new_uri = t->uac[t->relayed_reply_branch].uri;
00320 req->parsed_uri_ok = 0;
00321 } else {
00322 new_uri_bk.len = -1;
00323 new_uri_bk.s = 0;
00324 }
00325
00326
00327 env_set_to( get_rpl_to(t,reply) );
00328 env_set_code_status( code, reply);
00329
00330
00331
00332
00333
00334
00335 if (is_log_mc_on(req)) {
00336 env_set_text( ACC_MISSED, ACC_MISSED_LEN);
00337 acc_log_request( req );
00338 flags_to_reset |= log_missed_flag;
00339 }
00340 #ifdef SQL_ACC
00341 if (is_db_mc_on(req)) {
00342 env_set_text(db_table_mc.s, db_table_mc.len);
00343 acc_db_request( req );
00344 flags_to_reset |= db_missed_flag;
00345 }
00346 #endif
00347 #ifdef RAD_ACC
00348 if (is_rad_mc_on(req)) {
00349 acc_rad_request( req );
00350 flags_to_reset |= radius_missed_flag;
00351 }
00352 #endif
00353
00354 #ifdef DIAM_ACC
00355 if (is_diam_mc_on(req)) {
00356 acc_diam_request( req );
00357 flags_to_reset |= diameter_missed_flag;
00358 }
00359 #endif
00360
00361
00362 acc_run_engines(req, 1, &flags_to_reset);
00363
00364
00365
00366
00367
00368 reset_acc_flag( req, flags_to_reset );
00369
00370 if (new_uri_bk.len>=0) {
00371 req->new_uri = new_uri_bk;
00372 req->parsed_uri_ok = 0;
00373 }
00374
00375 }
00376
00377
00378
00379
00380 static inline void acc_onreply( struct cell* t, struct sip_msg *req,
00381 struct sip_msg *reply, int code)
00382 {
00383 str new_uri_bk;
00384
00385
00386
00387
00388 if (is_invite(t) && code>=300 && is_mc_on(req) )
00389 on_missed(t, req, reply, code);
00390
00391 if (!should_acc_reply(req, reply, code))
00392 return;
00393
00394
00395 if (t->relayed_reply_branch>=0) {
00396 new_uri_bk = req->new_uri;
00397 req->new_uri = t->uac[t->relayed_reply_branch].uri;
00398 req->parsed_uri_ok = 0;
00399 } else {
00400 new_uri_bk.len = -1;
00401 new_uri_bk.s = 0;
00402 }
00403
00404 env_set_to( get_rpl_to(t,reply) );
00405 env_set_code_status( code, reply);
00406
00407 if ( is_log_acc_on(req) ) {
00408 env_set_text( ACC_ANSWERED, ACC_ANSWERED_LEN);
00409 acc_log_request(req);
00410 }
00411 #ifdef SQL_ACC
00412 if (is_db_acc_on(req)) {
00413 env_set_text( db_table_acc.s, db_table_acc.len);
00414 acc_db_request(req);
00415 }
00416 #endif
00417 #ifdef RAD_ACC
00418 if (is_rad_acc_on(req))
00419 acc_rad_request(req);
00420 #endif
00421
00422 #ifdef DIAM_ACC
00423 if (is_diam_acc_on(req))
00424 acc_diam_request(req);
00425 #endif
00426
00427
00428 acc_run_engines(req, 0, NULL);
00429
00430 if (new_uri_bk.len>=0) {
00431 req->new_uri = new_uri_bk;
00432 req->parsed_uri_ok = 0;
00433 }
00434 }
00435
00436
00437
00438 static inline void acc_onack( struct cell* t, struct sip_msg *req,
00439 struct sip_msg *ack, int code)
00440 {
00441 if (acc_preparse_req(ack)<0)
00442 return;
00443
00444
00445 env_set_to( ack->to?ack->to:req->to );
00446 env_set_code_status( t->uas.status, 0 );
00447
00448 if (is_log_acc_on(req)) {
00449 env_set_text( ACC_ACKED, ACC_ACKED_LEN);
00450 acc_log_request( ack );
00451 }
00452 #ifdef SQL_ACC
00453 if (is_db_acc_on(req)) {
00454 env_set_text( db_table_acc.s, db_table_acc.len);
00455 acc_db_request( ack );
00456 }
00457 #endif
00458 #ifdef RAD_ACC
00459 if (is_rad_acc_on(req)) {
00460 acc_rad_request(ack);
00461 }
00462 #endif
00463
00464 #ifdef DIAM_ACC
00465 if (is_diam_acc_on(req)) {
00466 acc_diam_request(ack);
00467 }
00468 #endif
00469
00470
00471 acc_run_engines(req, 0, NULL);
00472
00473 }
00474
00475
00479 int acc_api_exec(struct sip_msg *rq, acc_engine_t *eng,
00480 acc_param_t* comment)
00481 {
00482 acc_info_t inf;
00483 if (acc_preparse_req(rq)<0)
00484 return -1;
00485 env_set_to(rq->to);
00486 env_set_comment(comment);
00487 memset(&inf, 0, sizeof(acc_info_t));
00488 inf.env = &acc_env;
00489 acc_api_set_arrays(&inf);
00490 return eng->acc_req(rq, &inf);
00491 }
00492
00493
00494 static void tmcb_func( struct cell* t, int type, struct tmcb_params *ps )
00495 {
00496 LM_DBG("acc callback called for t(%p) event type %d, reply code %d\n",
00497 t, type, ps->code);
00498 if (type&TMCB_RESPONSE_OUT) {
00499 acc_onreply( t, ps->req, ps->rpl, ps->code);
00500 } else if (type&TMCB_E2EACK_IN) {
00501 acc_onack( t, t->uas.request, ps->req, ps->code);
00502 } else if (type&TMCB_ON_FAILURE) {
00503 on_missed( t, ps->req, ps->rpl, ps->code);
00504 } else if (type&TMCB_RESPONSE_IN) {
00505 acc_onreply_in( t, ps->req, ps->rpl, ps->code);
00506 }
00507 }
00508