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
00031
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <time.h>
00035
00036 #include "../../sr_module.h"
00037 #include "../../dprint.h"
00038 #include "../../mem/mem.h"
00039 #include "../../modules/tm/t_hooks.h"
00040 #include "../../modules/tm/tm_load.h"
00041 #include "../../modules/tm/h_table.h"
00042 #include "../../parser/msg_parser.h"
00043 #include "../../parser/parse_from.h"
00044 #include "../../parser/digest/digest.h"
00045 #include "../../usr_avp.h"
00046 #include "../../modules/tm/tm_load.h"
00047 #include "../../usr_avp.h"
00048 #include "../../lib/srdb2/db.h"
00049 #include "../../trim.h"
00050 #include "../../id.h"
00051 #include "../acc_syslog/attrs.h"
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #define ALL_LOG_FMT "acdfgimnoprstuxDFIMPRSTUX"
00086 #define ALL_LOG_FMT_LEN (sizeof(ALL_LOG_FMT) - 1)
00087
00088
00089 #define A_ATTRS "attrs"
00090 #define A_CALLID "sip_callid"
00091 #define A_TOTAG "to_tag"
00092 #define A_FROM "sip_from"
00093 #define A_FLAGS "flags"
00094 #define A_IURI "in_ruri"
00095 #define A_METHOD "sip_method"
00096 #define A_CSEQ "sip_cseq"
00097 #define A_OURI "out_ruri"
00098 #define A_FROMTAG "from_tag"
00099 #define A_TO "sip_to"
00100 #define A_DIGUSER "digest_username"
00101 #define A_REQTIMESTAMP "request_timestamp"
00102 #define A_TODID "to_did"
00103 #define A_FROMURI "from_uri"
00104 #define A_FROMUID "from_uid"
00105 #define A_FROMDID "from_did"
00106 #define A_DIGREALM "digest_realm"
00107 #define A_STATUS "sip_status"
00108 #define A_TOURI "to_uri"
00109 #define A_TOUID "to_uid"
00110 #define A_RESTIMESTAMP "response_timestamp"
00111 #define A_SRCIP "src_ip"
00112 #define A_SRCPORT "src_port"
00113 #define A_SERVER_ID "server_id"
00114
00115 MODULE_VERSION
00116
00117 struct tm_binds tmb;
00118
00119 static int mod_init(void);
00120 static void mod_destroy(void);
00121 static int child_init(int rank);
00122 static int fix_log_flag( modparam_t type, void* val);
00123 static int fix_log_missed_flag( modparam_t type, void* val);
00124
00125 static int early_media = 0;
00126 static int failed_transactions = 0;
00127 static int report_cancels = 0;
00128 static int report_ack = 0;
00129 static int log_flag = 0;
00130 static int log_missed_flag = 0;
00131 static char* log_fmt = ALL_LOG_FMT;
00132
00133 #define DEFAULT_ACC_TABLE "acc"
00134 #define DEFAULT_MC_TABLE "missed_calls"
00135
00136 static str db_url = STR_STATIC_INIT(DEFAULT_DB_URL);
00137 static str acc_table = STR_STATIC_INIT(DEFAULT_ACC_TABLE);
00138 static str mc_table = STR_STATIC_INIT(DEFAULT_MC_TABLE);
00139
00140 static str attrs_col = STR_STATIC_INIT(A_ATTRS);
00141 static str callid_col = STR_STATIC_INIT(A_CALLID);
00142 static str totag_col = STR_STATIC_INIT(A_TOTAG);
00143 static str from_col = STR_STATIC_INIT(A_FROM);
00144 static str flags_col = STR_STATIC_INIT(A_FLAGS);
00145 static str iuri_col = STR_STATIC_INIT(A_IURI);
00146 static str method_col = STR_STATIC_INIT(A_METHOD);
00147 static str cseq_col = STR_STATIC_INIT(A_CSEQ);
00148 static str ouri_col = STR_STATIC_INIT(A_OURI);
00149 static str fromtag_col = STR_STATIC_INIT(A_FROMTAG);
00150 static str to_col = STR_STATIC_INIT(A_TO);
00151 static str diguser_col = STR_STATIC_INIT(A_DIGUSER);
00152 static str reqtimestamp_col = STR_STATIC_INIT(A_REQTIMESTAMP);
00153 static str todid_col = STR_STATIC_INIT(A_TODID);
00154 static str fromuri_col = STR_STATIC_INIT(A_FROMURI);
00155 static str fromuid_col = STR_STATIC_INIT(A_FROMUID);
00156 static str fromdid_col = STR_STATIC_INIT(A_FROMDID);
00157 static str digrealm_col = STR_STATIC_INIT(A_DIGREALM);
00158 static str status_col = STR_STATIC_INIT(A_STATUS);
00159 static str touri_col = STR_STATIC_INIT(A_TOURI);
00160 static str touid_col = STR_STATIC_INIT(A_TOUID);
00161 static str restimestamp_col = STR_STATIC_INIT(A_RESTIMESTAMP);
00162 static str src_ip_col = STR_STATIC_INIT(A_SRCIP);
00163 static str src_port_col = STR_STATIC_INIT(A_SRCPORT);
00164 static str server_id_col = STR_STATIC_INIT(A_SERVER_ID);
00165
00166 static db_ctx_t* acc_db = NULL;
00167 static db_fld_t fld[sizeof(ALL_LOG_FMT) - 1];
00168 static db_cmd_t* write_mc = NULL, *write_acc = NULL;
00169
00170
00171
00172 static char* attrs = "";
00173 avp_ident_t* avps;
00174 int avps_n;
00175
00176 static int acc_db_request0(struct sip_msg *rq, char *p1, char *p2);
00177 static int acc_db_missed0(struct sip_msg *rq, char *p1, char *p2);
00178 static int acc_db_request1(struct sip_msg *rq, char *p1, char *p2);
00179 static int acc_db_missed1(struct sip_msg *rq, char *p1, char *p2);
00180
00181 static cmd_export_t cmds[] = {
00182 {"acc_db_log", acc_db_request0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00183 {"acc_db_missed", acc_db_missed0, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
00184 {"acc_db_log", acc_db_request1, 1, fixup_var_int_1, REQUEST_ROUTE | FAILURE_ROUTE},
00185 {"acc_db_missed", acc_db_missed1, 1, fixup_var_int_1, REQUEST_ROUTE | FAILURE_ROUTE},
00186 {0, 0, 0, 0, 0}
00187 };
00188
00189
00190 static param_export_t params[] = {
00191 {"early_media", PARAM_INT, &early_media },
00192 {"failed_transactions", PARAM_INT, &failed_transactions },
00193 {"report_ack", PARAM_INT, &report_ack },
00194 {"report_cancels", PARAM_INT, &report_cancels },
00195 {"log_flag", PARAM_INT, &log_flag },
00196 {"log_flag", PARAM_STRING|PARAM_USE_FUNC, fix_log_flag},
00197 {"log_missed_flag", PARAM_INT, &log_missed_flag },
00198 {"log_missed_flag", PARAM_STRING|PARAM_USE_FUNC, fix_log_missed_flag},
00199 {"log_fmt", PARAM_STRING, &log_fmt },
00200 {"attrs", PARAM_STRING, &attrs },
00201 {"db_url", PARAM_STR, &db_url },
00202 {"acc_table", PARAM_STR, &acc_table },
00203 {"mc_table", PARAM_STR, &mc_table },
00204 {"attrs_column", PARAM_STR, &attrs_col },
00205 {"callid_column", PARAM_STR, &callid_col },
00206 {"totag_column", PARAM_STR, &totag_col },
00207 {"from_column", PARAM_STR, &from_col },
00208 {"flags_column", PARAM_STR, &flags_col },
00209 {"iuri_column", PARAM_STR, &iuri_col },
00210 {"method_column", PARAM_STR, &method_col },
00211 {"cseq_column", PARAM_STR, &cseq_col },
00212 {"ouri_column", PARAM_STR, &ouri_col },
00213 {"fromtag_column", PARAM_STR, &fromtag_col },
00214 {"to_column", PARAM_STR, &to_col },
00215 {"diguser_column", PARAM_STR, &diguser_col },
00216 {"reqtimestamp_column", PARAM_STR, &reqtimestamp_col },
00217 {"todid_column", PARAM_STR, &todid_col },
00218 {"fromuri_column", PARAM_STR, &fromuri_col },
00219 {"fromuid_column", PARAM_STR, &fromuid_col },
00220 {"fromdid_column", PARAM_STR, &fromdid_col },
00221 {"digrealm_column", PARAM_STR, &digrealm_col },
00222 {"status_column", PARAM_STR, &status_col },
00223 {"touri_column", PARAM_STR, &touri_col },
00224 {"touid_column", PARAM_STR, &touid_col },
00225 {"restimestamp_column", PARAM_STR, &restimestamp_col },
00226 {"src_ip_column", PARAM_STR, &src_ip_col },
00227 {"src_port_column", PARAM_STR, &src_port_col },
00228 {"server_id_column", PARAM_STR, &server_id_col},
00229 {0, 0, 0}
00230 };
00231
00232
00233 struct module_exports exports= {
00234 "acc_db",
00235 cmds,
00236 0,
00237 params,
00238 mod_init,
00239 0,
00240 mod_destroy,
00241 0,
00242 child_init
00243 };
00244
00245
00246
00247
00248 static int fix_log_flag( modparam_t type, void* val)
00249 {
00250 return fix_flag(type, val, "acc_db", "log_flag", &log_flag);
00251 }
00252
00253
00254
00255
00256 static int fix_log_missed_flag( modparam_t type, void* val)
00257 {
00258 return fix_flag(type, val, "acc_db", "log_missed_flag", &log_missed_flag);
00259 }
00260
00261
00262
00263 static inline int skip_cancel(struct sip_msg *msg)
00264 {
00265 return (msg->REQ_METHOD == METHOD_CANCEL) && report_cancels == 0;
00266 }
00267
00268 static int verify_fmt(char *fmt) {
00269
00270 if (!fmt) {
00271 LOG(L_ERR, "ERROR:acc:verify_fmt: formatting string zero\n");
00272 return -1;
00273 }
00274
00275 if (!(*fmt)) {
00276 LOG(L_ERR, "ERROR:acc:verify_fmt: formatting string empty\n");
00277 return -1;
00278 }
00279
00280 if (strlen(fmt) > ALL_LOG_FMT_LEN) {
00281 LOG(L_ERR, "ERROR:acc:verify_fmt: formatting string too long\n");
00282 return -1;
00283 }
00284
00285 while(*fmt) {
00286 if (!strchr(ALL_LOG_FMT, *fmt)) {
00287 LOG(L_ERR, "ERROR:acc:verify_fmt: char in log_fmt invalid: %c\n", *fmt);
00288 return -1;
00289 }
00290 fmt++;
00291 }
00292 return 1;
00293 }
00294
00295
00296
00297
00298
00299
00300 static inline int is_acc_on(struct sip_msg *rq)
00301 {
00302 return log_flag && isflagset(rq, log_flag) == 1;
00303 }
00304
00305
00306
00307
00308
00309
00310 static inline int is_mc_on(struct sip_msg *rq)
00311 {
00312 return log_missed_flag && isflagset(rq, log_missed_flag) == 1;
00313 }
00314
00315
00316 static inline void preparse_req(struct sip_msg *rq)
00317 {
00318
00319
00320
00321
00322
00323
00324 parse_headers(rq, HDR_CALLID_F | HDR_FROM_F | HDR_TO_F | HDR_CSEQ_F, 0 );
00325 parse_from_header(rq);
00326 }
00327
00328
00329
00330 static inline int should_acc_reply(struct cell* t, int code)
00331 {
00332 struct sip_msg *r;
00333
00334 r = t->uas.request;
00335
00336
00337 if (r == 0) {
00338 LOG(L_ERR, "ERROR:acc:should_acc_reply: 0 request\n");
00339 return 0;
00340 }
00341
00342
00343
00344 if (!failed_transactions && code >= 300) return 0;
00345 if (!is_acc_on(r)) return 0;
00346 if (skip_cancel(r)) return 0;
00347 if (code < 200 && ! (early_media && code == 183)) return 0;
00348 return 1;
00349 }
00350
00351
00352
00353 static inline str* cred_user(struct sip_msg* rq)
00354 {
00355 struct hdr_field* h;
00356 auth_body_t* cred;
00357
00358 get_authorized_cred(rq->proxy_auth, &h);
00359 if (!h) get_authorized_cred(rq->authorization, &h);
00360 if (!h) return 0;
00361 cred = (auth_body_t*)(h->parsed);
00362 if (!cred || !cred->digest.username.user.len)
00363 return 0;
00364 return &cred->digest.username.user;
00365 }
00366
00367
00368
00369 static inline str* cred_realm(struct sip_msg* rq)
00370 {
00371 str* realm;
00372 struct hdr_field* h;
00373 auth_body_t* cred;
00374
00375 get_authorized_cred(rq->proxy_auth, &h);
00376 if (!h) get_authorized_cred(rq->authorization, &h);
00377 if (!h) return 0;
00378 cred = (auth_body_t*)(h->parsed);
00379 if (!cred) return 0;
00380 realm = GET_REALM(&cred->digest);
00381 if (!realm->len || !realm->s) {
00382 return 0;
00383 }
00384 return realm;
00385 }
00386
00387
00388
00389
00390
00391 static inline struct hdr_field* valid_to(struct cell* t, struct sip_msg* reply)
00392 {
00393 if (reply == FAKED_REPLY || !reply || !reply->to) {
00394 return t->uas.request->to;
00395 } else {
00396 return reply->to;
00397 }
00398 }
00399
00400
00401 static int init_data(char* fmt)
00402 {
00403 int i = 0;
00404
00405 memset(fld, '\0', sizeof(fld));
00406 while(*fmt) {
00407 switch(*fmt) {
00408 case 'a':
00409 fld[i].name = attrs_col.s;
00410 fld[i].type = DB_STR;
00411 break;
00412
00413 case 'c':
00414 fld[i].type = DB_STR;
00415 fld[i].name = callid_col.s;
00416 break;
00417
00418 case 'd':
00419 fld[i].type = DB_STR;
00420 fld[i].name = totag_col.s;
00421 break;
00422
00423 case 'f':
00424 fld[i].type = DB_STR;
00425 fld[i].name = from_col.s;
00426 break;
00427
00428 case 'g':
00429 fld[i].type = DB_INT;
00430 fld[i].name = flags_col.s;
00431 break;
00432
00433 case 'i':
00434 fld[i].type = DB_STR;
00435 fld[i].name = iuri_col.s;
00436 break;
00437
00438 case 'm':
00439 fld[i].type = DB_STR;
00440 fld[i].name = method_col.s;
00441 break;
00442
00443 case 'n':
00444 fld[i].type = DB_INT;
00445 fld[i].name = cseq_col.s;
00446 break;
00447
00448 case 'o':
00449 fld[i].type = DB_STR;
00450 fld[i].name = ouri_col.s;
00451 break;
00452
00453 case 'p':
00454 fld[i].type = DB_INT;
00455 fld[i].name = src_ip_col.s;
00456 break;
00457
00458 case 'r':
00459 fld[i].type = DB_STR;
00460 fld[i].name = fromtag_col.s;
00461 break;
00462
00463 case 't':
00464 fld[i].type = DB_STR;
00465 fld[i].name = to_col.s;
00466 break;
00467
00468 case 'u':
00469 fld[i].type = DB_STR;
00470 fld[i].name = diguser_col.s;
00471 break;
00472
00473 case 'x':
00474 fld[i].type = DB_DATETIME;
00475 fld[i].name = reqtimestamp_col.s;
00476 break;
00477
00478 case 'D':
00479 fld[i].type = DB_STR;
00480 fld[i].name = todid_col.s;
00481 break;
00482
00483 case 'F':
00484 fld[i].type = DB_STR;
00485 fld[i].name = fromuri_col.s;
00486 break;
00487
00488 case 'I':
00489 fld[i].type = DB_STR;
00490 fld[i].name = fromuid_col.s;
00491 break;
00492
00493 case 'M':
00494 fld[i].type = DB_STR;
00495 fld[i].name = fromdid_col.s;
00496 break;
00497
00498 case 'P':
00499 fld[i].type = DB_INT;
00500 fld[i].name = src_port_col.s;
00501 break;
00502
00503 case 'R':
00504 fld[i].type = DB_STR;
00505 fld[i].name = digrealm_col.s;
00506 break;
00507
00508 case 'S':
00509 fld[i].type = DB_INT;
00510 fld[i].name = status_col.s;
00511 break;
00512
00513 case 'T':
00514 fld[i].type = DB_STR;
00515 fld[i].name = touri_col.s;
00516 break;
00517
00518 case 'U':
00519 fld[i].type = DB_STR;
00520 fld[i].name = touid_col.s;
00521 break;
00522
00523 case 'X':
00524 fld[i].type = DB_DATETIME;
00525 fld[i].name = restimestamp_col.s;
00526 break;
00527
00528 case 's':
00529 fld[i].type = DB_INT;
00530 fld[i].name = server_id_col.s;
00531 }
00532
00533 fmt++;
00534 i++;
00535 }
00536 fld[i].name = NULL;
00537 return 0;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 static int fmt2strar(char *fmt,
00549 struct sip_msg *rq,
00550 str* ouri,
00551 struct hdr_field *to,
00552 unsigned int code,
00553 time_t req_time,
00554 db_fld_t* params)
00555 {
00556 int cnt;
00557 struct to_body* from, *pto;
00558 str *cr, *at;
00559 struct cseq_body *cseq;
00560
00561 cnt = 0;
00562
00563
00564
00565
00566
00567
00568
00569 while(*fmt) {
00570 if (cnt == ALL_LOG_FMT_LEN) {
00571 LOG(L_ERR, "ERROR:acc:fmt2strar: Formatting string is too long\n");
00572 return 0;
00573 }
00574
00575 params[cnt].flags &= ~DB_NULL;
00576 switch(*fmt) {
00577 case 'a':
00578 at = print_attrs(avps, avps_n, 0);
00579 if (!at) {
00580 params[cnt].flags |= DB_NULL;
00581 } else {
00582 params[cnt].v.lstr = *at;
00583 }
00584 break;
00585
00586 case 'c':
00587 if (rq->callid && rq->callid->body.len) {
00588 params[cnt].v.lstr = rq->callid->body;
00589 } else {
00590 params[cnt].flags |= DB_NULL;
00591 }
00592 break;
00593
00594 case 'd':
00595 if (to && (pto = (struct to_body*)(to->parsed)) && pto->tag_value.len) {
00596 params[cnt].v.lstr = pto->tag_value;
00597 } else {
00598 params[cnt].flags |= DB_NULL;
00599 }
00600 break;
00601
00602 case 'f':
00603 if (rq->from && rq->from->body.len) {
00604 params[cnt].v.lstr = rq->from->body;
00605 } else {
00606 params[cnt].flags |= DB_NULL;
00607 }
00608 break;
00609
00610 case 'g':
00611 params[cnt].v.int4 = rq->flags;
00612 break;
00613
00614 case 'i':
00615 params[cnt].v.lstr = rq->first_line.u.request.uri;
00616 break;
00617
00618 case 'm':
00619 params[cnt].v.lstr = rq->first_line.u.request.method;
00620 break;
00621
00622 case 'n':
00623 if (rq->cseq && (cseq = get_cseq(rq)) && cseq->number.len) {
00624 str2int(&cseq->number, (unsigned int*)¶ms[cnt].v.int4);
00625 } else {
00626 params[cnt].flags |= DB_NULL;
00627 }
00628 break;
00629
00630 case 'o':
00631 params[cnt].v.lstr = *ouri;
00632 break;
00633
00634 case 'p':
00635 params[cnt].v.int4 = rq->rcv.src_ip.u.addr32[0];
00636 break;
00637
00638 case 'r':
00639 if (rq->from && (from = get_from(rq)) && from->tag_value.len) {
00640 params[cnt].v.lstr = from->tag_value;
00641 } else {
00642 params[cnt].flags |= DB_NULL;
00643 }
00644 break;
00645
00646 case 't':
00647 if (to && to->body.len) params[cnt].v.lstr = to->body;
00648 else params[cnt].flags |= DB_NULL;
00649 break;
00650
00651 case 'u':
00652 cr = cred_user(rq);
00653 if (cr) params[cnt].v.lstr = *cr;
00654 else params[cnt].flags |= DB_NULL;
00655 break;
00656
00657 case 'x':
00658 params[cnt].v.time = req_time;
00659 break;
00660
00661 case 'D':
00662 params[cnt].flags |= DB_NULL;
00663 break;
00664
00665 case 'F':
00666 if (rq->from && (from = get_from(rq)) && from->uri.len) {
00667 params[cnt].v.lstr = from->uri;
00668 } else params[cnt].flags |= DB_NULL;
00669 break;
00670
00671 case 'I':
00672 if (get_from_uid(¶ms[cnt].v.lstr, rq) < 0) {
00673 params[cnt].flags |= DB_NULL;
00674 }
00675 break;
00676
00677 case 'M':
00678 params[cnt].flags |= DB_NULL;
00679 break;
00680
00681 case 'P':
00682 params[cnt].v.int4 = rq->rcv.src_port;
00683 break;
00684
00685 case 'R':
00686 cr = cred_realm(rq);
00687 if (cr) params[cnt].v.lstr = *cr;
00688 else params[cnt].flags |= DB_NULL;
00689 break;
00690
00691 case 's':
00692 params[cnt].v.int4 = server_id;
00693 break;
00694
00695 case 'S':
00696 if (code > 0) params[cnt].v.int4 = code;
00697 else params[cnt].flags |= DB_NULL;
00698 break;
00699
00700 case 'T':
00701 if (rq->to && (pto = get_to(rq)) && pto->uri.len) params[cnt].v.lstr = pto->uri;
00702 else params[cnt].flags |= DB_NULL;
00703 break;
00704
00705 case 'U':
00706 if (get_to_uid(¶ms[cnt].v.lstr, rq) < 0) {
00707 params[cnt].flags |= DB_NULL;
00708 }
00709 break;
00710
00711 case 'X':
00712 params[cnt].v.time = time(0);
00713 break;
00714
00715 default:
00716 LOG(L_CRIT, "BUG:acc:fmt2strar: unknown char: %c\n", *fmt);
00717 return 0;
00718 }
00719
00720 fmt++;
00721 cnt++;
00722 }
00723
00724 return cnt;
00725 }
00726
00727
00728 int log_request(struct sip_msg *rq, str* ouri, struct hdr_field *to, db_cmd_t* cmd, unsigned int code, time_t req_timestamp)
00729 {
00730 int cnt;
00731 if (skip_cancel(rq)) return 1;
00732
00733 cnt = fmt2strar(log_fmt, rq, ouri, to, code, req_timestamp, cmd->vals);
00734 if (cnt == 0) {
00735 LOG(L_ERR, "ERROR:acc:log_request: fmt2strar failed\n");
00736 return -1;
00737 }
00738
00739 if (!db_url.len) {
00740 LOG(L_ERR, "ERROR:acc:log_request: can't log -- no db_url set\n");
00741 return -1;
00742 }
00743
00744 if (db_exec(NULL, cmd) < 0) {
00745 ERR("Error while inserting to database\n");
00746 return -1;
00747 }
00748
00749 return 1;
00750 }
00751
00752
00753 static void log_reply(struct cell* t , struct sip_msg* reply, unsigned int code, time_t req_time)
00754 {
00755 str* ouri;
00756
00757 if (t->relayed_reply_branch >= 0) {
00758 ouri = &t->uac[t->relayed_reply_branch].uri;
00759 } else {
00760 ouri = GET_NEXT_HOP(t->uas.request);
00761 }
00762
00763 log_request(t->uas.request, ouri, valid_to(t,reply), write_acc, code, req_time);
00764 }
00765
00766
00767 static void log_ack(struct cell* t , struct sip_msg *ack, time_t req_time)
00768 {
00769 struct sip_msg *rq;
00770 struct hdr_field *to;
00771
00772 rq = t->uas.request;
00773 if (ack->to) to = ack->to;
00774 else to = rq->to;
00775
00776 log_request(ack, GET_RURI(ack), to, write_acc, t->uas.status, req_time);
00777 }
00778
00779
00780 static void log_missed(struct cell* t, struct sip_msg* reply, unsigned int code, time_t req_time)
00781 {
00782 str* ouri;
00783
00784 if (t->relayed_reply_branch >= 0) {
00785 ouri = &t->uac[t->relayed_reply_branch].uri;
00786 } else {
00787 ouri = GET_NEXT_HOP(t->uas.request);
00788 }
00789
00790 log_request(t->uas.request, ouri, valid_to(t, reply), write_mc, code, req_time);
00791 }
00792
00793
00794
00795
00796
00797
00798 static int acc_db_request0(struct sip_msg *rq, char* s1, char* s2)
00799 {
00800 preparse_req(rq);
00801 return log_request(rq, GET_RURI(rq), rq->to, write_acc, 0, time(0));
00802 }
00803
00804
00805
00806
00807
00808
00809 static int acc_db_missed0(struct sip_msg *rq, char* s1, char* s2)
00810 {
00811 preparse_req(rq);
00812 return log_request(rq, GET_RURI(rq), rq->to, write_mc, 0, time(0));
00813 }
00814
00815
00816
00817
00818
00819
00820 static int acc_db_request1(struct sip_msg *rq, char* p1, char* p2)
00821 {
00822 int code;
00823
00824 if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) {
00825 code = 0;
00826 }
00827 preparse_req(rq);
00828 return log_request(rq, GET_RURI(rq), rq->to, write_acc, code, time(0));
00829 }
00830
00831
00832
00833
00834
00835
00836 static int acc_db_missed1(struct sip_msg *rq, char* p1, char* p2)
00837 {
00838 int code;
00839
00840 if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) {
00841 code = 0;
00842 }
00843 preparse_req(rq);
00844 return log_request(rq, GET_RURI(rq), rq->to, write_mc, code, time(0));
00845 }
00846
00847
00848 static void ack_handler(struct cell* t, int type, struct tmcb_params* ps)
00849 {
00850 if (is_acc_on(t->uas.request)) {
00851 preparse_req(ps->req);
00852 log_ack(t, ps->req, (time_t)*(ps->param));
00853 }
00854 }
00855
00856
00857
00858 static void failure_handler(struct cell *t, int type, struct tmcb_params* ps)
00859 {
00860
00861 if (t->uas.request == 0) {
00862 DBG("DBG:acc:failure_handler: No uas.request, skipping local transaction\n");
00863 return;
00864 }
00865
00866 if (is_invite(t) && ps->code >= 300) {
00867 if (is_mc_on(t->uas.request)) {
00868 log_missed(t, ps->rpl, ps->code, (time_t)*(ps->param));
00869 resetflag(t->uas.request, log_missed_flag);
00870 }
00871 }
00872 }
00873
00874
00875
00876 static void replyout_handler(struct cell* t, int type, struct tmcb_params* ps)
00877 {
00878 if (t->uas.request == 0) {
00879 DBG("DBG:acc:replyout_handler: No uas.request, local transaction, skipping\n");
00880 return;
00881 }
00882
00883
00884
00885
00886
00887 failure_handler(t, type, ps);
00888 if (!should_acc_reply(t, ps->code)) return;
00889 if (is_acc_on(t->uas.request)) log_reply(t, ps->rpl, ps->code, (time_t)*(ps->param));
00890 }
00891
00892
00893
00894 static void replyin_handler(struct cell *t, int type, struct tmcb_params* ps)
00895 {
00896
00897 if (t->uas.request == 0) {
00898 LOG(L_ERR, "ERROR:acc:replyin_handler:replyin_handler: 0 request\n");
00899 return;
00900 }
00901
00902
00903
00904 if (((is_invite(t) && ps->code >= 300 && is_mc_on(t->uas.request))
00905 || should_acc_reply(t, ps->code))
00906 && (ps->rpl && ps->rpl != FAKED_REPLY)) {
00907 parse_headers(ps->rpl, HDR_TO_F, 0);
00908 }
00909 }
00910
00911
00912
00913 static void on_req(struct cell* t, int type, struct tmcb_params *ps)
00914 {
00915 time_t req_time;
00916
00917 req_time = time(0);
00918
00919 if (is_acc_on(ps->req) || is_mc_on(ps->req)) {
00920 if (tmb.register_tmcb(0, t, TMCB_RESPONSE_OUT, replyout_handler,
00921 (void*)req_time, 0) <= 0) {
00922 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_RESPONSE_OUT callback\n");
00923 return;
00924 }
00925
00926 if (report_ack) {
00927 if (tmb.register_tmcb(0, t, TMCB_E2EACK_IN, ack_handler,
00928 (void*)req_time, 0) <= 0) {
00929 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_E2EACK_IN callback\n");
00930 return;
00931 }
00932 }
00933
00934 if (tmb.register_tmcb(0, t, TMCB_ON_FAILURE_RO, failure_handler,
00935 (void*)req_time, 0) <= 0) {
00936 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_ON_FAILURE_RO callback\n");
00937 return;
00938 }
00939
00940 if (tmb.register_tmcb(0, t, TMCB_RESPONSE_IN, replyin_handler,
00941 (void*)req_time, 0) <= 0) {
00942 LOG(L_ERR, "ERROR:acc:on_req: Error while registering TMCB_RESPONSE_IN callback\n");
00943 return;
00944 }
00945
00946
00947 preparse_req(ps->req);
00948
00949 if (ps->req->REQ_METHOD == METHOD_INVITE) {
00950 DBG("DEBUG: noisy_timer set for accounting\n");
00951 t->flags |= T_NOISY_CTIMER_FLAG;
00952 }
00953 }
00954 }
00955
00956
00957 static int child_init(int rank)
00958 {
00959 if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00960 return 0;
00961
00962 if (db_url.s) {
00963 acc_db = db_ctx("acc_db");
00964 if (acc_db == NULL) {
00965 ERR("Error while initializing database layer\n");
00966 return -1;
00967 }
00968
00969 if (db_add_db(acc_db, db_url.s) < 0) goto error;
00970 if (db_connect(acc_db) < 0) goto error;
00971
00972 write_acc = db_cmd(DB_PUT, acc_db, acc_table.s, NULL, NULL, fld);
00973 if (write_acc == NULL) {
00974 ERR("Error while compiling database query\n");
00975 goto error;
00976 }
00977
00978 write_mc = db_cmd(DB_PUT, acc_db, mc_table.s, NULL, NULL, fld);
00979 if (write_mc == NULL) {
00980 ERR("Error while compiling database query\n");
00981 goto error;
00982 }
00983
00984 return 0;
00985 } else {
00986 LOG(L_CRIT, "BUG:acc:child_init: null db url\n");
00987 return -1;
00988 }
00989 error:
00990 if (write_acc) db_cmd_free(write_acc);
00991 write_acc = NULL;
00992 if (write_mc) db_cmd_free(write_mc);
00993 write_mc = NULL;
00994 if (acc_db) db_ctx_free(acc_db);
00995 acc_db = NULL;
00996 return -1;
00997 }
00998
00999
01000 static void mod_destroy(void)
01001 {
01002 if (write_mc) db_cmd_free(write_mc);
01003 if (write_acc) db_cmd_free(write_acc);
01004 if (acc_db) {
01005 db_disconnect(acc_db);
01006 db_ctx_free(acc_db);
01007 }
01008 }
01009
01010
01011 static int mod_init(void)
01012 {
01013 load_tm_f load_tm;
01014
01015
01016 if ( !(load_tm = (load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
01017 LOG(L_ERR, "ERROR:acc:mod_init: can't import load_tm\n");
01018 return -1;
01019 }
01020
01021 if (load_tm( &tmb )==-1) return -1;
01022 if (verify_fmt(log_fmt)==-1) return -1;
01023
01024
01025
01026 if (tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, on_req, 0, 0) <= 0) {
01027 LOG(L_ERR,"ERROR:acc:mod_init: cannot register TMCB_REQUEST_IN "
01028 "callback\n");
01029 return -1;
01030 }
01031
01032 init_data(log_fmt);
01033
01034 if (parse_attrs(&avps, &avps_n, attrs) < 0) {
01035 ERR("Error while parsing 'attrs' module parameter\n");
01036 return -1;
01037 }
01038
01039 return 0;
01040 }