diff --git a/cdr/cdr_beanstalkd.c b/cdr/cdr_beanstalkd.c index 524274ffb765442bea0511483d5d822c93f52d72..b79739251896643b53a2927df74c5427cd76bd07 100644 --- a/cdr/cdr_beanstalkd.c +++ b/cdr/cdr_beanstalkd.c @@ -195,7 +195,9 @@ static int beanstalk_put(struct ast_cdr *cdr) { ast_rwlock_unlock(&config_lock); - t_cdr_json = ast_json_pack("{s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:i, s:i, s:s, s:s, s:s, s:s}", + t_cdr_json = ast_json_pack("{s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:i, s:i, s:s, s:s, s:s, s:i, s:s, s:s, + s:i, s:s, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, + s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:i, s:s}", "AccountCode", S_OR(cdr->accountcode, ""), "Source", S_OR(cdr->src, ""), "Destination", S_OR(cdr->dst, ""), @@ -213,6 +215,35 @@ static int beanstalk_put(struct ast_cdr *cdr) { "Disposition", S_OR(ast_cdr_disp2str(cdr->disposition), ""), "AMAFlags", S_OR(ast_channel_amaflags2string(cdr->amaflags), ""), "UniqueID", S_OR(cdr->uniqueid, ""), + "SessionId", cdr->sessionId, + "sipIpAddress", S_OR(cdr->sipIpAddress, ""), + "farEndIPAddress", S_OR(cdr->farEndIPAddress, ""), + "sipResponseCode", cdr->sipResponseCode, + "codec", S_OR(cdr->codec, ""), + "localBurstDensity", cdr->rtp_stats->localBurstDensity, + "remoteBurstDensity", cdr->rtp_stats->remoteBurstDensity, + "localBurstDuration", cdr->rtp_stats->localBurstDuration, + "remoteBurstDuration", cdr->rtp_stats->remoteBurstDuration, + "localGapDensity", cdr->rtp_stats->localGapDensity, + "remoteGapDensity", cdr->rtp_stats->remoteGapDensity, + "localGapDuration", cdr->rtp_stats->localGapDuration, + "remoteGapDuration", cdr->rtp_stats->remoteGapDuration, + "localJbRate", cdr->rtp_stats->localJbRate, + "remoteJbRate", cdr->rtp_stats->remoteJbRate, + "localJbMax", cdr->rtp_stats->localJbMax, + "remoteJbMax", cdr->rtp_stats->remoteJbMax, + "localJbNominal", cdr->rtp_stats->localJbNominal, + "remoteJbNominal", cdr->rtp_stats->remoteJbNominal, + "localJbAbsMax", cdr->rtp_stats->localJbAbsMax, + "remoteJbAbsMax", cdr->rtp_stats->remoteJbAbsMax, + "jbAvg", cdr->rtp_stats->jbAvg, + "uLossRate", cdr->rtp_stats->uLossRate, + "discarded", cdr->rtp_stats->discarded, + "lost", cdr->rtp_stats->lost, + "rxpkts", cdr->rtp_stats->rxpkts, + "txpkts", cdr->rtp_stats->txpkts, + "jitter", cdr->rtp_stats->jitter, + "maxJitter", cdr->rtp_stats->maxJitter, "UserField", S_OR(cdr->userfield, "")); cdr_buffer = ast_json_dump_string(t_cdr_json); diff --git a/cdr/cdr_csv.c b/cdr/cdr_csv.c index e4c74ff1efbb4d3b0f4b54937d9397adf71b8002..d8249e5f57f054154b68d849579d7c741eeb3550 100644 --- a/cdr/cdr_csv.c +++ b/cdr/cdr_csv.c @@ -242,6 +242,44 @@ static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr) append_int(buf, cdr->billsec, bufsize); /* Disposition */ append_string(buf, ast_cdr_disp2str(cdr->disposition), bufsize); + /* Session Id */ + append_int(buf, cdr->sessionId, bufsize); + /* SIP IP Address */ + append_string(buf, cdr->sipIpAddress, bufsize); + /* Far End IP Address */ + append_string(buf, cdr->farEndIPAddress, bufsize); + /* Sip Response Code */ + append_int(buf, cdr->sipResponseCode, bufsize); + /* codec */ + append_string(buf, cdr->codec, bufsize); + + /* RTP statistics */ + if (cdr->rtp_stats) { + append_int(buf, cdr->rtp_stats->localBurstDensity, bufsize); + append_int(buf, cdr->rtp_stats->remoteBurstDensity, bufsize); + append_int(buf, cdr->rtp_stats->localBurstDuration, bufsize); + append_int(buf, cdr->rtp_stats->remoteBurstDuration, bufsize); + append_int(buf, cdr->rtp_stats->localGapDensity, bufsize); + append_int(buf, cdr->rtp_stats->remoteGapDensity, bufsize); + append_int(buf, cdr->rtp_stats->localGapDuration, bufsize); + append_int(buf, cdr->rtp_stats->remoteGapDuration, bufsize); + append_int(buf, cdr->rtp_stats->localJbRate, bufsize); + append_int(buf, cdr->rtp_stats->remoteJbRate, bufsize); + append_int(buf, cdr->rtp_stats->localJbMax, bufsize); + append_int(buf, cdr->rtp_stats->remoteJbMax, bufsize); + append_int(buf, cdr->rtp_stats->localJbNominal, bufsize); + append_int(buf, cdr->rtp_stats->remoteJbNominal, bufsize); + append_int(buf, cdr->rtp_stats->localJbAbsMax, bufsize); + append_int(buf, cdr->rtp_stats->remoteJbAbsMax, bufsize); + append_int(buf, cdr->rtp_stats->jbAvg, bufsize); + append_int(buf, cdr->rtp_stats->uLossRate, bufsize); + append_int(buf, cdr->rtp_stats->discarded, bufsize); + append_int(buf, cdr->rtp_stats->lost, bufsize); + append_int(buf, cdr->rtp_stats->rxpkts, bufsize); + append_int(buf, cdr->rtp_stats->txpkts, bufsize); + append_int(buf, cdr->rtp_stats->jitter, bufsize); + append_int(buf, cdr->rtp_stats->maxJitter, bufsize); + } /* AMA Flags */ append_string(buf, ast_channel_amaflags2string(cdr->amaflags), bufsize); /* Unique ID */ diff --git a/cdr/cdr_manager.c b/cdr/cdr_manager.c index 74f37d207f3c56396a4158e90c8ad3f661b73914..ffb51ced184e2c291c2161f8b27dabab7503fcd0 100644 --- a/cdr/cdr_manager.c +++ b/cdr/cdr_manager.c @@ -324,12 +324,48 @@ static int manager_log(struct ast_cdr *cdr) "Disposition: %s\r\n" "AMAFlags: %s\r\n" "UniqueID: %s\r\n" + "SessionId: %ld\r\n" + "SipIpAddress: %s\r\n" + "farEndIPAddress: %s\r\n" + "sipResponseCode: %ld\r\n" + "codec: %s\r\n" + "localBurstDensity: %ld\r\n" + "remoteBurstDensity: %ld\r\n" + "localBurstDuration: %ld\r\n" + "remoteBurstDuration: %ld\r\n" + "localGapDensity: %ld\r\n" + "remoteGapDensity: %ld\r\n" + "localGapDuration: %ld\r\n" + "remoteGapDuration: %ld\r\n" + "localJbRate: %ld\r\n" + "remoteJbRate: %ld\r\n" + "localJbMax: %ld\r\n" + "remoteJbMax: %ld\r\n" + "localJbNominal: %ld\r\n" + "remoteJbNominal: %ld\r\n" + "localJbAbsMax: %ld\r\n" + "remoteJbAbsMax: %ld\r\n" + "jbAvg: %ld\r\n" + "discarded: %ld\r\n" + "discarded: %ld\r\n" + "lost: %ld\r\n" + "rxpkts: %ld\r\n" + "txpkts: %ld\r\n" + "jitter: %ld\r\n" + "maxJitter: %ld\r\n" "UserField: %s\r\n" "%s", cdr->accountcode, cdr->src, cdr->dst, cdr->dcontext, cdr->clid, cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, strStartTime, strAnswerTime, strEndTime, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), - ast_channel_amaflags2string(cdr->amaflags), cdr->uniqueid, cdr->userfield,buf); + ast_channel_amaflags2string(cdr->amaflags), cdr->uniqueid, cdr->sessionId, + cdr->sipIpAddress, cdr->farEndIPAddress, cdr->sipResponseCode, cdr->codec, cdr->rtp_stats->localBurstDensity, + cdr->rtp_stats->remoteBurstDensity, cdr->rtp_stats->localBurstDuration, cdr->rtp_stats->remoteBurstDuration, cdr->rtp_stats->localGapDensity, + cdr->rtp_stats->remoteGapDensity, cdr->rtp_stats->localGapDuration, cdr->rtp_stats->remoteGapDuration, cdr->rtp_stats->localJbRate, + cdr->rtp_stats->remoteJbRate, cdr->rtp_stats->localJbMax, cdr->rtp_stats->remoteJbMax, cdr->rtp_stats->localJbNominal, + cdr->rtp_stats->remoteJbNominal, cdr->rtp_stats->localJbAbsMax, cdr->rtp_stats->remoteJbAbsMax, cdr->rtp_stats->jbAvg, + cdr->rtp_stats->uLossRate, cdr->rtp_stats->discarded, cdr->rtp_stats->lost, cdr->rtp_stats->rxpkts, + cdr->rtp_stats->txpkts, cdr->rtp_stats->jitter, cdr->rtp_stats->maxJitter, cdr->userfield, buf); return 0; } diff --git a/cdr/cdr_odbc.c b/cdr/cdr_odbc.c index 43305869b1738846e334b463654af440a3b6bdad..0e09b5e810300f8dfda84bcba0d66d94f0a262aa 100644 --- a/cdr/cdr_odbc.c +++ b/cdr/cdr_odbc.c @@ -149,10 +149,41 @@ static SQLHSTMT execute_cb(struct odbc_obj *obj, void *data) if (ast_test_flag(&config, CONFIG_NEWCDRCOLUMNS)) { SQLBindParameter(stmt, i, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->peeraccount), 0, cdr->peeraccount, 0, NULL); - SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->linkedid), 0, cdr->linkedid, 0, NULL); - SQLBindParameter(stmt, i + 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->sequence, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->linkedid), 0, cdr->linkedid, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->sequence, 0, NULL); } + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->sessionId, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->sipIpAddress), 0, cdr->sipIpAddress, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->farEndIPAddress), 0, cdr->farEndIPAddress, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->sipResponseCode, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->codec), 0, cdr->codec, 0, NULL); + + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localBurstDensity, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteBurstDensity, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localBurstDuration, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteBurstDuration, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localGapDensity, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteGapDensity, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localGapDuration, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteGapDuration, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localJbRate, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteJbRate, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localJbMax, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteJbMax, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localJbNominal, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteJbNominal, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->localJbAbsMax, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->remoteJbAbsMax, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->jbAvg, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->uLossRate, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->discarded, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->lost, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->rxpkts, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->txpkts, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->jitter, 0, NULL); + SQLBindParameter(stmt, i++, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->rtp_stats->maxJitter, 0, NULL); + ODBC_res = ast_odbc_execute_sql(obj, stmt, sqlcmd); if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { diff --git a/cdr/cdr_radius.c b/cdr/cdr_radius.c index 0a5fa6371c98358a1b6f598d7442a4f8178949e1..d68e76f344891af2258da4db7c5e5d99d8ec3ab9 100644 --- a/cdr/cdr_radius.c +++ b/cdr/cdr_radius.c @@ -69,7 +69,36 @@ enum { PW_AST_DISPOSITION = 115, PW_AST_AMA_FLAGS = 116, PW_AST_UNIQUE_ID = 117, - PW_AST_USER_FIELD = 118 + PW_AST_USER_FIELD = 118, + PW_AST_USER_SESSION_ID = 119, + PW_AST_SIP_IP_ADDR = 120, + PW_AST_FAR_END_IP_ADDR = 121, + PW_AST_SIP_RESPONSE_CODE = 122, + PW_AST_CODEC = 123, + PW_AST_RTP_LOCAL_BURST_DENSITY = 124, + PW_AST_RTP_REMOTE_BURST_DENSITY = 125, + PW_AST_RTP_LOCAL_BURST_DURATION = 126, + PW_AST_RTP_REMOTE_BURST_DURATION = 127, + PW_AST_RTP_LOCAL_GAP_DENSITY = 128, + PW_AST_RTP_REMOTE_GAP_DENSITY = 129, + PW_AST_RTP_LOCAL_GAP_DURATION = 130, + PW_AST_RTP_REMOTE_GAP_DURATION = 131, + PW_AST_RTP_LOCAL_JB_RATE = 132, + PW_AST_RTP_REMOTE_JB_RATE = 133, + PW_AST_RTP_LOCAL_JB_MAX = 134, + PW_AST_RTP_REMOTE_JB_MAX = 135, + PW_AST_RTP_LOCAL_JB_NOMINAL = 136, + PW_AST_RTP_REMOTE_JB_NOMINAL = 137, + PW_AST_RTP_LOCAL_JB_ABS_MAX = 138, + PW_AST_RTP_REMOTE_JB_ABS_MAX = 139, + PW_AST_RTP_JB_AVG = 140, + PW_AST_RTP_LOSS_RATE = 141, + PW_AST_RTP_DISCARDED = 142, + PW_AST_RTP_LOST = 143, + PW_AST_RTP_RX_PKTS = 144, + PW_AST_RTP_TX_PKTS = 145, + PW_AST_RTP_JITTER = 146, + PW_AST_RTP_MAX_JITTER = 147 }; enum { @@ -193,6 +222,77 @@ static int build_radius_record(VALUE_PAIR **tosend, struct ast_cdr *cdr) return -1; } + /* Session Id */ + if (!rc_avpair_add(rh, tosend, PW_AST_USER_SESSION_ID, &cdr->sessionId, 0, VENDOR_CODE)) + return -1; + + /* SIP IP Address */ + if (!rc_avpair_add(rh, tosend, PW_AST_SIP_IP_ADDR, &cdr->sipIpAddress, strlen(cdr->sipIpAddress), VENDOR_CODE)) + return -1; + + /* Far End IP Address */ + if (!rc_avpair_add(rh, tosend, PW_AST_FAR_END_IP_ADDR, &cdr->farEndIPAddress, strlen(cdr->farEndIPAddress), VENDOR_CODE)) + return -1; + + /* Sip Response Code */ + if (!rc_avpair_add(rh, tosend, PW_AST_SIP_RESPONSE_CODE, &cdr->sipResponseCode, 0, VENDOR_CODE)) + return -1; + + /* codec */ + if (!rc_avpair_add(rh, tosend, PW_AST_CODEC, &cdr->codec, strlen(cdr->codec), VENDOR_CODE)) + return -1; + + /* RTP statistics */ + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_BURST_DENSITY, &cdr->rtp_stats->localBurstDensity, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_BURST_DENSITY, &cdr->rtp_stats->remoteBurstDensity, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_BURST_DURATION, &cdr->rtp_stats->localBurstDuration, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_BURST_DURATION, &cdr->rtp_stats->remoteBurstDuration, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_GAP_DENSITY, &cdr->rtp_stats->localGapDensity, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_GAP_DENSITY, &cdr->rtp_stats->remoteGapDensity, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_GAP_DURATION, &cdr->rtp_stats->localGapDuration, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_GAP_DURATION, &cdr->rtp_stats->remoteGapDuration, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_JB_RATE, &cdr->rtp_stats->localJbRate, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_JB_RATE, &cdr->rtp_stats->remoteJbRate, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_JB_MAX, &cdr->rtp_stats->localJbMax, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_JB_MAX, &cdr->rtp_stats->remoteJbMax, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_JB_NOMINAL, &cdr->rtp_stats->localJbNominal, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_JB_NOMINAL, &cdr->rtp_stats->remoteJbNominal, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOCAL_JB_ABS_MAX, &cdr->rtp_stats->localJbAbsMax, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_REMOTE_JB_ABS_MAX, &cdr->rtp_stats->remoteJbAbsMax, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_JB_AVG, &cdr->rtp_stats->jbAvg, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOSS_RATE, &cdr->rtp_stats->uLossRate, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_DISCARDED, &cdr->rtp_stats->discarded, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_LOST, &cdr->rtp_stats->lost, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_RX_PKTS, &cdr->rtp_stats->rxpkts, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_TX_PKTS, &cdr->rtp_stats->txpkts, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_JITTER, &cdr->rtp_stats->jitter, 0, VENDOR_CODE)) + return -1; + if (!rc_avpair_add(rh, tosend, PW_AST_RTP_MAX_JITTER, &cdr->rtp_stats->maxJitter, 0, VENDOR_CODE)) + return -1; + + /* Setting Acct-Session-Id & User-Name attributes for proper generation * of Acct-Unique-Session-Id on server side */ diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c index 2de4e426ae7199b5f74c23caa0b65c7be4507985..5c6f743fc53ab2200773b35ad8a2a9bcb6793bf6 100644 --- a/cdr/cdr_tds.c +++ b/cdr/cdr_tds.c @@ -189,13 +189,22 @@ retry: "(" "'%s', '%s', '%s', '%s', '%s', '%s', " "'%s', '%s', '%s', %s, %s, %s, %ld, " - "%ld, '%s', '%s', '%s', '%s'" - ")", + "%ld, '%s', '%s', '%s', %ld , '%s' " + "'%s', %ld , '%s', %ld , %ld , %ld , + %ld , %ld , %ld , %ld , %ld , %ld , + %ld , %ld , %ld , %ld , %ld , %ld , + %ld , %ld , %ld , %ld , %ld , %ld , + %ld , %ld , %ld ,'%s')", settings->table, accountcode, src, dst, dcontext, clid, channel, dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid, - userfield + cdr->sessionId, cdr->sipIpAddress, cdr->farEndIPAddress, cdr->sipResponseCode, cdr->codec, cdr->rtp_stats->localBurstDensity, + cdr->rtp_stats->remoteBurstDensity, cdr->rtp_stats->localBurstDuration, cdr->rtp_stats->remoteBurstDuration, cdr->rtp_stats->localGapDensity, cdr->rtp_stats->remoteGapDensity, + cdr->rtp_stats->localGapDuration, cdr->rtp_stats->remoteGapDuration, cdr->rtp_stats->localJbRate, cdr->rtp_stats->remoteJbRate, cdr->rtp_stats->localJbMax, + cdr->rtp_stats->remoteJbMax, cdr->rtp_stats->localJbNominal, cdr->rtp_stats->remoteJbNominal, cdr->rtp_stats->localJbAbsMax, cdr->rtp_stats->remoteJbAbsMax, + cdr->rtp_stats->jbAvg, cdr->rtp_stats->uLossRate, cdr->rtp_stats->discarded, cdr->rtp_stats->lost, cdr->rtp_stats->rxpkts, + cdr->rtp_stats->txpkts, cdr->rtp_stats->jitter, cdr->rtp_stats->maxJitter, userfield ); } } else { @@ -238,12 +247,20 @@ retry: "(" "'%s', '%s', '%s', '%s', '%s', '%s', " "'%s', '%s', '%s', %s, %s, %s, %ld, " - "%ld, '%s', '%s', '%s'" - ")", + "%ld, '%s', '%s', %ld , '%s', '%s', %ld, " + "'%s', %ld, %ld, %ld, %ld, %ld, %ld, %ld, + %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, + %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld, '%s')", settings->table, accountcode, src, dst, dcontext, clid, channel, dstchannel, lastapp, lastdata, start, answer, end, cdr->duration, - cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), uniqueid + cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_channel_amaflags2string(cdr->amaflags), + cdr->sessionId, cdr->sipIpAddress, cdr->farEndIPAddress, cdr->sipResponseCode, cdr->codec, + cdr->rtp_stats->localBurstDensity, cdr->rtp_stats->remoteBurstDensity, cdr->rtp_stats->localBurstDuration, cdr->rtp_stats->remoteBurstDuration, + cdr->rtp_stats->localGapDensity, cdr->rtp_stats->remoteGapDensity, cdr->rtp_stats->localGapDuration, cdr->rtp_stats->remoteGapDuration, + cdr->rtp_stats->localJbRate, cdr->rtp_stats->remoteJbRate, cdr->rtp_stats->localJbMax, cdr->rtp_stats->remoteJbMax, cdr->rtp_stats->localJbNominal, + cdr->rtp_stats->remoteJbNominal, cdr->rtp_stats->localJbAbsMax, cdr->rtp_stats->remoteJbAbsMax, cdr->rtp_stats->jbAvg, cdr->rtp_stats->uLossRate, + cdr->rtp_stats->discarded, cdr->rtp_stats->lost, cdr->rtp_stats->rxpkts, cdr->rtp_stats->txpkts, cdr->rtp_stats->jitter, cdr->rtp_stats->maxJitter, uniqueid ); } } diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c index b263432fb538689f4d2a483dc1f9330db275307e..7a7e9fa0bd8295e0cdc1589e82fc44c6a0105506 100644 --- a/channels/chan_brcm.c +++ b/channels/chan_brcm.c @@ -123,6 +123,7 @@ static struct ast_channel *brcm_new(struct brcm_subchannel *subchan, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_format_cap *format); static int handle_dialtone_timeout(const void *data); +static int endpt_get_rtp_stats(int line); /* Global brcm channel parameters */ static const char tdesc[] = "Broadcom SLIC Driver"; @@ -135,6 +136,7 @@ static int num_fxo_endpoints = -1; static int num_dect_endpoints = -1; static int num_endpoints = -1; static int clip = 1; // Caller ID presentation +static rtp_statistics rtp_stats = {0}; /* driver scheduler */ static struct ast_sched_context *sched = NULL; @@ -427,7 +429,6 @@ static void ubus_call_complete(struct ubus_request *req, int ret) free(req); } - static void endpt_signal(int line, char *signal, char *state, char *data) { struct blob_buf bb; struct ubus_request *req; @@ -817,7 +818,7 @@ static int brcm_call(struct ast_channel *chan, const char *dest, int timeout) ast_debug(1, "Line is busy\n"); ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY); ast_queue_control(chan, AST_CONTROL_BUSY); - send_ubus_event("USER_BUSY",p->line_id); + send_ubus_event("USER_BUSY",p->line_id); } else { ast_debug(1, "Not call waiting\n"); @@ -830,7 +831,11 @@ static int brcm_call(struct ast_channel *chan, const char *dest, int timeout) } ast_setstate(chan, AST_STATE_RINGING); ast_queue_control(chan, AST_CONTROL_RINGING); - send_ubus_event("RINGING",p->line_id); + send_ubus_event("RINGING",p->line_id); + if (!sub->connection_init) { + sub->connection_id = ast_atomic_fetchadd_int((int *)¤t_connection_id, +1); + brcm_create_connection(sub); + } } //ast_mutex_unlock(&sub->parent->lock); pvt_unlock(sub->parent); @@ -882,6 +887,12 @@ static int brcm_hangup(struct ast_channel *ast) ast_channel_name(ast), p->line_id, sub->connection_id, dialtone_map[p->dialtone].str, state2str(sub->channel_state)); + if (endpt_get_rtp_stats(p->line_id)) + if (endpt_get_rtp_stats(p->line_id)) // retry once if failed + ast_log(LOG_WARNING, "Unable to get RTP statistics\n"); + + ast_channel_rtpStats_set(ast, &rtp_stats); + if (sub->channel_state == CALLWAITING) { brcm_stop_callwaiting(p); } else if (sub_peer->channel_state == ONHOLD && @@ -2446,7 +2457,6 @@ static void *brcm_process_event(struct endpt_event *ev) { if (owner) { ast_queue_control(owner, AST_CONTROL_HANGUP); - endpt_connection(sub->parent->line_id, sub->connection_id, "destroy"); } //TODO: possible bug below - we don't change the channel_state when hanging up @@ -3383,6 +3393,61 @@ static const struct blobmsg_policy endpt_count_policy[__MAX_ENDPOINTS] = { [NUM_DECT_ENDPOINTS] = { .name = "num_dect_endpoints", .type = BLOBMSG_TYPE_INT32 }, }; +enum { + RTP_STATS_LOCAL_BURST_DENSITY, + RTP_STATS_REMOTE_BURST_DENSITY, + RTP_STATS_LOCAL_BURST_DURATION, + RTP_STATS_REMOTE_BURST_DURATION, + RTP_STATS_LOCAL_GAP_DENSITY, + RTP_STATS_REMOTE_GAP_DENSITY, + RTP_STATS_LOCAL_GAP_DURATION, + RTP_STATS_REMOTE_GAP_DURATION, + RTP_STATS_LOCAL_JB_RATE, + RTP_STATS_REMOTE_JB_RATE, + RTP_STATS_LOCAL_JB_MAX, + RTP_STATS_REMOTE_JB_MAX, + RTP_STATS_LOCAL_JB_NOMINAL, + RTP_STATS_REMOTE_JB_NOMINAL, + RTP_STATS_LOCAL_JB_ABS_MAX, + RTP_STATS_REMOTE_JB_ABS_MAX, + RTP_STATS_DISCARDED, + RTP_STATS_LOST, + RTP_STATS_RX_PKTS, + RTP_STATS_TX_PKTS, + RTP_STATS_JB_AVG, + RTP_STATS_JITTER, + RTP_STATS_LOSS_RATE, + RTP_STATS_MAX_JITTER, + __MAX_RTP_STATS, +}; + +static const struct blobmsg_policy endpt_rtp_stats_policy[__MAX_RTP_STATS] = { + [RTP_STATS_LOCAL_BURST_DENSITY] = { .name = "localBurstDensity", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_BURST_DENSITY] = { .name = "remoteBurstDensity", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_LOCAL_BURST_DURATION] = { .name = "localBurstDuration", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_BURST_DURATION] = { .name = "remoteBurstDuration", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_LOCAL_GAP_DENSITY] = { .name = "localGapDensity", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_GAP_DENSITY] = { .name = "remoteGapDensity", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_LOCAL_GAP_DURATION] = { .name = "localGapDuration", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_GAP_DURATION] = { .name = "remoteGapDuration", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_LOCAL_JB_RATE] = { .name = "localJbRate", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_JB_RATE] = { .name = "remoteJbRate", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_LOCAL_JB_MAX] = { .name = "localJbMax", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_JB_MAX] = { .name = "remoteJbMax", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_LOCAL_JB_NOMINAL] = { .name = "localJbNominal", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_JB_NOMINAL] = { .name = "remoteJbNominal", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_LOCAL_JB_ABS_MAX] = { .name = "localJbAbsMax", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_REMOTE_JB_ABS_MAX] = { .name = "remoteJbAbsMax", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_DISCARDED] = { .name = "discarded", .type = BLOBMSG_TYPE_INT32 }, + [RTP_STATS_LOST] = { .name = "lost", .type = BLOBMSG_TYPE_INT32 }, + [RTP_STATS_RX_PKTS] = { .name = "rxpkts", .type = BLOBMSG_TYPE_INT32 }, + [RTP_STATS_TX_PKTS] = { .name = "txpkts", .type = BLOBMSG_TYPE_INT32 }, + [RTP_STATS_JB_AVG] = { .name = "jbAvg", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_JITTER] = { .name = "jitter", .type = BLOBMSG_TYPE_INT32 }, + [RTP_STATS_LOSS_RATE] = { .name = "uLossRate", .type = BLOBMSG_TYPE_INT16 }, + [RTP_STATS_MAX_JITTER] = { .name = "maxJitter", .type = BLOBMSG_TYPE_INT32 }, +}; + // Reception of event // { "ubus.object.add": {"id":123, "path":"foo"} } static void ubus_event_new_obj(struct ubus_context *ctx __attribute__((unused)), struct ubus_event_handler *ev __attribute__((unused)), @@ -3447,6 +3512,93 @@ static int endpt_get_count(void) { endpt_get_count_cb, NULL, 2000) == UBUS_STATUS_OK ? 0 : -1); } +static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struct blob_attr *msg) { + struct blob_attr *tb[__MAX_RTP_STATS]; + + ast_log(LOG_DEBUG, "Got answer from endptmngr on rtp_stats ubus call.\n"); + blobmsg_parse(endpt_rtp_stats_policy, __MAX_RTP_STATS, tb, blob_data(msg), blob_len(msg)); + + if (tb[RTP_STATS_LOCAL_BURST_DENSITY]) + rtp_stats.localBurstDensity = blobmsg_get_u16(tb[RTP_STATS_LOCAL_BURST_DENSITY]); + if (tb[RTP_STATS_REMOTE_BURST_DENSITY]) + rtp_stats.remoteBurstDensity = blobmsg_get_u16(tb[RTP_STATS_REMOTE_BURST_DENSITY]); + if (tb[RTP_STATS_LOCAL_BURST_DURATION]) + rtp_stats.localBurstDuration = blobmsg_get_u16(tb[RTP_STATS_LOCAL_BURST_DURATION]); + if (tb[RTP_STATS_REMOTE_BURST_DURATION]) + rtp_stats.remoteBurstDuration = blobmsg_get_u16(tb[RTP_STATS_REMOTE_BURST_DURATION]); + if (tb[RTP_STATS_LOCAL_GAP_DENSITY]) + rtp_stats.localGapDensity = blobmsg_get_u16(tb[RTP_STATS_LOCAL_GAP_DENSITY]); + if (tb[RTP_STATS_REMOTE_GAP_DENSITY]) + rtp_stats.remoteGapDensity = blobmsg_get_u16(tb[RTP_STATS_REMOTE_GAP_DENSITY]); + if (tb[RTP_STATS_LOCAL_GAP_DURATION]) + rtp_stats.localGapDuration = blobmsg_get_u16(tb[RTP_STATS_LOCAL_GAP_DURATION]); + if (tb[RTP_STATS_REMOTE_GAP_DURATION]) + rtp_stats.remoteGapDuration = blobmsg_get_u16(tb[RTP_STATS_REMOTE_GAP_DURATION]); + if (tb[RTP_STATS_LOCAL_JB_RATE]) + rtp_stats.localJbRate = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_RATE]); + if (tb[RTP_STATS_REMOTE_JB_RATE]) + rtp_stats.remoteJbRate = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_RATE]); + if (tb[RTP_STATS_LOCAL_JB_MAX]) + rtp_stats.localJbMax = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_MAX]); + if (tb[RTP_STATS_REMOTE_JB_MAX]) + rtp_stats.remoteJbMax = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_MAX]); + if (tb[RTP_STATS_LOCAL_JB_NOMINAL]) + rtp_stats.localJbNominal = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_NOMINAL]); + if (tb[RTP_STATS_REMOTE_JB_NOMINAL]) + rtp_stats.remoteJbNominal = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_NOMINAL]); + if (tb[RTP_STATS_LOCAL_JB_ABS_MAX]) + rtp_stats.localJbAbsMax = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_ABS_MAX]); + if (tb[RTP_STATS_REMOTE_JB_ABS_MAX]) + rtp_stats.remoteJbAbsMax = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_ABS_MAX]); + if (tb[RTP_STATS_DISCARDED]) + rtp_stats.discarded = blobmsg_get_u32(tb[RTP_STATS_DISCARDED]); + if (tb[RTP_STATS_LOST]) + rtp_stats.lost = blobmsg_get_u32(tb[RTP_STATS_LOST]); + if (tb[RTP_STATS_RX_PKTS]) + rtp_stats.rxpkts = blobmsg_get_u32(tb[RTP_STATS_RX_PKTS]); + if (tb[RTP_STATS_TX_PKTS]) + rtp_stats.txpkts = blobmsg_get_u32(tb[RTP_STATS_TX_PKTS]); + if (tb[RTP_STATS_JB_AVG]) + rtp_stats.jbAvg = blobmsg_get_u16(tb[RTP_STATS_JB_AVG]); + if (tb[RTP_STATS_JITTER]) + rtp_stats.jitter = blobmsg_get_u32(tb[RTP_STATS_JITTER]); + if (tb[RTP_STATS_LOSS_RATE]) + rtp_stats.uLossRate = blobmsg_get_u16(tb[RTP_STATS_LOSS_RATE]); + if (tb[RTP_STATS_MAX_JITTER]) + rtp_stats.maxJitter = blobmsg_get_u32(tb[RTP_STATS_MAX_JITTER]); + + ast_log(LOG_DEBUG, "RTP stats received:\nlocalBurstDensity: %d\nremoteBurstDensity: %d\n" + "localBurstDuration: %d\nremoteBurstDuration: %d\nlocalGapDensity: %d\n" + "remoteGapDensity: %d\nlocalGapDuration: %d\nremoteGapDuration: %d\n" + "localJbRate: %d\nremoteJbRate: %d\nlocalJbMax: %d\nremoteJbMax: %d\n" + "localJbNominal: %d\nremoteJbNominal: %d\nlocalJbAbsMax: %d\n" + "remoteJbAbsMax: %d\ndiscarded: %d\nlost: %d\nrxpkts: %d\ntxpkts: %d\n" + "jbAvg: %d\njitter: %d\nuLossRate: %d\nmaxJitter: %d\n", + rtp_stats.localBurstDensity, rtp_stats.remoteBurstDensity, rtp_stats.localBurstDuration, + rtp_stats.remoteBurstDuration, rtp_stats.localGapDensity, rtp_stats.remoteGapDensity, + rtp_stats.localGapDuration, rtp_stats.remoteGapDuration, rtp_stats.localJbRate, + rtp_stats.remoteJbRate, rtp_stats.localJbMax, rtp_stats.remoteJbMax, rtp_stats.localJbNominal, + rtp_stats.remoteJbNominal, rtp_stats.localJbAbsMax, rtp_stats.remoteJbAbsMax, rtp_stats.discarded, + rtp_stats.lost, rtp_stats.rxpkts, rtp_stats.txpkts, rtp_stats.jbAvg, rtp_stats.jitter, + rtp_stats.uLossRate, rtp_stats.maxJitter); +} + +static int endpt_get_rtp_stats(int line) { + struct blob_buf bb; + int res; + + if (endpt_id) { + memset(&bb, 0, sizeof(bb)); + blob_buf_init(&bb, 0); + + blobmsg_add_u32(&bb, "line", line); + blobmsg_add_u8(&bb, "reset", 1); // always reset RTP stats after get them + + return (ubus_invoke(ctx, endpt_id, "rtp_stats", bb.head, + ubus_call_answer_rtp_stats, NULL, 2000) == UBUS_STATUS_OK ? 0 : -1); + } +} + // Reception of RPC call // ubus call asterisk event '{ "line" : 1, "event" : "EVENT_DTMF0" }' static int asterisk_event(struct ubus_context *ctx, struct ubus_object *obj, diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h index c6b241315c836e1011c002641e4b12da4ce48683..ce947bfc42b5ae2eec63f7b221c8a64d3f8d8685 100644 --- a/include/asterisk/cdr.h +++ b/include/asterisk/cdr.h @@ -270,6 +270,34 @@ struct ast_cdr_config { } batch_settings; }; +/*! \brief Struct for rtp statistics get from brcm */ +typedef struct { + uint16_t localBurstDensity; + uint16_t remoteBurstDensity; + uint16_t localBurstDuration; + uint16_t remoteBurstDuration; + uint16_t localGapDensity; + uint16_t remoteGapDensity; + uint16_t localGapDuration; + uint16_t remoteGapDuration; + uint16_t localJbRate; + uint16_t remoteJbRate; + uint16_t localJbMax; + uint16_t remoteJbMax; + uint16_t localJbNominal; + uint16_t remoteJbNominal; + uint16_t localJbAbsMax; + uint16_t remoteJbAbsMax; + uint16_t jbAvg; + uint16_t uLossRate; + uint32_t discarded; + uint32_t lost; + uint32_t rxpkts; + uint32_t txpkts; + uint32_t jitter; + uint32_t maxJitter; +} cdr_rtp_statistics; + /*! * \brief Responsible for call detail data */ @@ -318,7 +346,18 @@ struct ast_cdr { char userfield[AST_MAX_USER_FIELD]; /*! Sequence field */ int sequence; - + /*! SessionId */ + int sessionId; + /*! sipIpAddress */ + char sipIpAddress[40]; + /*! farEndIPAddress */ + char farEndIPAddress[40]; + /*! Sip Response Code */ + int sipResponseCode; + /*! codec */ + char codec[40]; + /*! RTP Statistics */ + cdr_rtp_statistics *rtp_stats; /*! A linked list for variables */ struct varshead varshead; diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 40069b0178db246a7afcdbb30781e66922b5f61c..3bf020e1a4492b43532494a19992158411ef853f 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -598,6 +598,34 @@ typedef struct { const char *value; } ast_chan_write_info_t; +/*! \brief Struct for rtp statistics get from brcm */ +typedef struct { + uint16_t localBurstDensity; + uint16_t remoteBurstDensity; + uint16_t localBurstDuration; + uint16_t remoteBurstDuration; + uint16_t localGapDensity; + uint16_t remoteGapDensity; + uint16_t localGapDuration; + uint16_t remoteGapDuration; + uint16_t localJbRate; + uint16_t remoteJbRate; + uint16_t localJbMax; + uint16_t remoteJbMax; + uint16_t localJbNominal; + uint16_t remoteJbNominal; + uint16_t localJbAbsMax; + uint16_t remoteJbAbsMax; + uint16_t jbAvg; + uint16_t uLossRate; + uint32_t discarded; + uint32_t lost; + uint32_t rxpkts; + uint32_t txpkts; + uint32_t jitter; + uint32_t maxJitter; +} rtp_statistics; + /*! * \brief Structure to pass both assignedid values to channel drivers * \note The second value is used only by core_unreal (LOCAL) @@ -4363,9 +4391,19 @@ enum ast_channel_adsicpe ast_channel_adsicpe(const struct ast_channel *chan); void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value); enum ast_channel_state ast_channel_state(const struct ast_channel *chan); ast_callid ast_channel_callid(const struct ast_channel *chan); +unsigned int ast_channel_sessionId(const struct ast_channel *chan); +void ast_channel_sessionId_set(struct ast_channel *chan, unsigned int value); +const char *ast_channel_sipIpAddress(const struct ast_channel *chan); +void ast_channel_sipIpAddress_set(struct ast_channel *chan, const char *value, size_t size); +const char *ast_channel_farEndIPAddress(const struct ast_channel *chan); +void ast_channel_farEndIPAddress_set(struct ast_channel *chan, const char *value, size_t size); +unsigned int ast_channel_sipResponseCode(const struct ast_channel *chan); +void ast_channel_sipResponseCode_set(struct ast_channel *chan, unsigned int value); struct ast_channel_snapshot *ast_channel_snapshot(const struct ast_channel *chan); void ast_channel_snapshot_set(struct ast_channel *chan, struct ast_channel_snapshot *snapshot); struct ast_flags *ast_channel_snapshot_segment_flags(struct ast_channel *chan); +rtp_statistics *ast_channel_rtpStats(const struct ast_channel *chan); +void ast_channel_rtpStats_set(struct ast_channel *chan, rtp_statistics *rtp_stats); /*! * \pre chan is locked diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h index 61f1c213a91f40ccb99b4a2848c66e9fd30dfe96..0d0875ce890897fce50816828c1050b35b547aa9 100644 --- a/include/asterisk/stasis_channels.h +++ b/include/asterisk/stasis_channels.h @@ -156,6 +156,12 @@ struct ast_channel_snapshot { struct ast_flags softhangup_flags; /*!< softhangup channel flags */ struct varshead *manager_vars; /*!< Variables to be appended to manager events */ struct varshead *ari_vars; /*!< Variables to be appended to ARI events */ + unsigned int sessionId; /*!< Session Id */ + char sipIpAddress[40]; /*!< SIP IP Address */ + char farEndIPAddress[40]; /*!< Far End IP Address */ + unsigned int sipResponseCode; /*!< SIP Response Code for Invite */ + char codec[40]; /*!< Codec used */ + rtp_statistics *rtp_stats; /*!< Rtp statistics */ }; /*! diff --git a/main/cdr.c b/main/cdr.c index 6a823a980710c96ab222e41f89de7192cf80b3d8..e549db6e92bd0db0847cd50e5966010b3e9014a6 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -731,7 +731,13 @@ struct cdr_object { AST_STRING_FIELD(context); /*!< The accepted context for Party A */ AST_STRING_FIELD(exten); /*!< The accepted extension for Party A */ AST_STRING_FIELD(party_b_name); /*!< Party B channel name. Cached here as it is the all CDRs container key */ + AST_STRING_FIELD(sipIpAddress); /*!< SIP IP Address */ + AST_STRING_FIELD(farEndIPAddress); /*!< Far End IP Address */ + AST_STRING_FIELD(codec); /*!< Codec used */ ); + unsigned int sessionId; /*!< Session Id */ + unsigned int sipResponseCode; /*!< Sip Response Code on Invite */ + cdr_rtp_statistics *rtp_stats; /*!< RTP Statistics */ struct cdr_object *next; /*!< The next CDR object in the chain */ struct cdr_object *last; /*!< The last CDR object in the chain */ int is_root; /*!< True if this is the first CDR in the chain */ @@ -1324,6 +1330,28 @@ static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr) ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst)); ast_copy_string(cdr_copy->dcontext, it_cdr->context, sizeof(cdr_copy->dcontext)); + if (party_a->sessionId) + cdr_copy->sessionId = party_a->sessionId; + + if (ast_strlen_zero(cdr_copy->sipIpAddress) && !ast_strlen_zero(party_a->sipIpAddress)) { + ast_copy_string(cdr_copy->sipIpAddress, party_a->sipIpAddress, sizeof(cdr_copy->sipIpAddress)); + } + + if (ast_strlen_zero(cdr_copy->farEndIPAddress) && !ast_strlen_zero(party_a->farEndIPAddress)) { + ast_copy_string(cdr_copy->farEndIPAddress, party_a->farEndIPAddress, sizeof(cdr_copy->farEndIPAddress)); + } + + if (party_a->sipResponseCode) { + cdr_copy->sipResponseCode = party_a->sipResponseCode; + + } + if (ast_strlen_zero(cdr_copy->codec) && !ast_strlen_zero(party_a->codec)) { + ast_copy_string(cdr_copy->codec, party_a->codec, sizeof(cdr_copy->codec)); + } + + if (party_a->rtp_stats) + cdr_copy->rtp_stats = party_a->rtp_stats; + /* Party B */ if (party_b) { ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel)); @@ -1331,7 +1359,29 @@ static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr) if (!ast_strlen_zero(it_cdr->party_b.userfield)) { snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield); } + if (party_b->sessionId) + cdr_copy->sessionId = party_b->sessionId; + + if (ast_strlen_zero(cdr_copy->sipIpAddress) && !ast_strlen_zero(party_b->sipIpAddress)) { + ast_copy_string(cdr_copy->sipIpAddress, party_b->sipIpAddress, sizeof(cdr_copy->sipIpAddress)); + } + + if (ast_strlen_zero(cdr_copy->farEndIPAddress) && !ast_strlen_zero(party_b->farEndIPAddress)) { + ast_copy_string(cdr_copy->farEndIPAddress, party_b->farEndIPAddress, sizeof(cdr_copy->farEndIPAddress)); + } + + if (party_b->sipResponseCode) { + cdr_copy->sipResponseCode = party_b->sipResponseCode; + } + + if (ast_strlen_zero(cdr_copy->codec) && !ast_strlen_zero(party_b->codec)) { + ast_copy_string(cdr_copy->codec, party_b->codec, sizeof(cdr_copy->codec)); + } + + if (party_b->rtp_stats) + cdr_copy->rtp_stats = party_b->rtp_stats; } + if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) { ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield)); } @@ -2284,7 +2334,6 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub if (filter_channel_snapshot_message(update->old_snapshot, update->new_snapshot)) { return; } - if (update->new_snapshot && !update->old_snapshot) { cdr = cdr_object_alloc(update->new_snapshot, stasis_message_timestamp(message)); if (!cdr) { @@ -2295,7 +2344,9 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub } else { cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY); } - + if (update->new_snapshot->rtp_stats){ + cdr->party_a.snapshot->rtp_stats = update->new_snapshot->rtp_stats; + } /* Handle Party A */ if (!cdr) { ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name); @@ -2347,7 +2398,6 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY, cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot); } - ao2_cleanup(cdr); } @@ -3110,6 +3160,64 @@ void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char snprintf(workspace, workspacelen, "%d", cdr->sequence); } else if ((varbuf = cdr_format_var_internal(cdr, name))) { ast_copy_string(workspace, varbuf, workspacelen); + } else if (!strcasecmp(name, "sessionId")) { + snprintf(workspace, workspacelen, "%ld", cdr->sessionId); + } else if (!strcasecmp(name, "sipIpAddress")) { + ast_copy_string(workspace, cdr->sipIpAddress, workspacelen); + } else if (!strcasecmp(name, "farEndIPAddress")) { + ast_copy_string(workspace, cdr->farEndIPAddress, workspacelen); + } else if (!strcasecmp(name, "sipResponseCode")) { + snprintf(workspace, workspacelen, "%ld", cdr->sipResponseCode); + } else if (!strcasecmp(name, "codec")) { + ast_copy_string(workspace, cdr->codec, workspacelen); + } else if (!strcasecmp(name, "localBurstDensity")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localBurstDensity); + } else if (!strcasecmp(name, "remoteBurstDensity")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteBurstDensity); + } else if (!strcasecmp(name, "localBurstDuration")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localBurstDuration); + } else if (!strcasecmp(name, "remoteBurstDuration")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteBurstDuration); + } else if (!strcasecmp(name, "localGapDensity")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localGapDensity); + } else if (!strcasecmp(name, "remoteGapDensity")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteGapDensity); + } else if (!strcasecmp(name, "localGapDuration")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localGapDuration); + } else if (!strcasecmp(name, "remoteGapDuration")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteGapDuration); + } else if (!strcasecmp(name, "localJbRate")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localJbRate); + } else if (!strcasecmp(name, "remoteJbRate")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteJbRate); + } else if (!strcasecmp(name, "localJbMax")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localJbMax); + } else if (!strcasecmp(name, "remoteJbMax")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteJbMax); + } else if (!strcasecmp(name, "localJbNominal")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localJbNominal); + } else if (!strcasecmp(name, "remoteJbNominal")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteJbNominal); + } else if (!strcasecmp(name, "localJbAbsMax")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->localJbAbsMax); + } else if (!strcasecmp(name, "remoteJbAbsMax")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->remoteJbAbsMax); + } else if (!strcasecmp(name, "jbAvg")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->jbAvg); + } else if (!strcasecmp(name, "uLossRate")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->uLossRate); + } else if (!strcasecmp(name, "discarded")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->discarded); + } else if (!strcasecmp(name, "lost")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->lost); + } else if (!strcasecmp(name, "rxpkts")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->rxpkts); + } else if (!strcasecmp(name, "txpkts")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->txpkts); + } else if (!strcasecmp(name, "jitter")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->jitter); + } else if (!strcasecmp(name, "maxJitter")) { + snprintf(workspace, workspacelen, "%ld", cdr->rtp_stats->maxJitter); } else { workspace[0] = '\0'; } diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index a84534aabf22c250a203d2579844454edc2c1224..1b3ebda9bbf3b7500be1ba8777c73170d052340e 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -222,6 +222,12 @@ struct ast_channel { struct ast_stream *default_streams[AST_MEDIA_TYPE_END]; /*!< Default streams indexed by media type */ struct ast_channel_snapshot *snapshot; /*!< The current up to date snapshot of the channel */ struct ast_flags snapshot_segment_flags; /*!< Flags regarding the segments of the snapshot */ + unsigned int sessionId; /*!< Session Id from SDP for channel */ + char sipIpAddress[40]; /*!< local IP address that sip client binds to */ + char farEndIPAddress[40]; /*!< Far End IP Address */ + unsigned int sipResponseCode; /*!< SIP response Code */ + char codec[40]; /*!< Negotiated codec used */ + rtp_statistics *rtp_stats; /*!< RTP statistics */ }; /*! \brief The monotonically increasing integer counter for channel uniqueids */ @@ -794,6 +800,57 @@ ast_callid ast_channel_callid(const struct ast_channel *chan) { return chan->callid; } +unsigned int ast_channel_sessionId(const struct ast_channel *chan) +{ + return chan->sessionId; +} +void ast_channel_sessionId_set(struct ast_channel *chan, unsigned int value) +{ + chan->sessionId = value; +} +const char *ast_channel_sipIpAddress(const struct ast_channel *chan) +{ + return chan->sipIpAddress; +} +void ast_channel_sipIpAddress_set(struct ast_channel *chan, const char *value, size_t size) +{ + ast_copy_string(chan->sipIpAddress, value, size+1); +} +const char *ast_channel_farEndIPAddress(const struct ast_channel *chan) +{ + return chan->farEndIPAddress; +} +void ast_channel_farEndIPAddress_set(struct ast_channel *chan, const char *value, size_t size) +{ + ast_copy_string(chan->farEndIPAddress, value, size+1); +} +unsigned int ast_channel_sipResponseCode(const struct ast_channel *chan) +{ + return chan->sipResponseCode; +} +void ast_channel_sipResponseCode_set(struct ast_channel *chan, unsigned int value) +{ + chan->sipResponseCode = value; +} + +const char *ast_channel_codec_get(const struct ast_channel *chan) +{ + return chan->codec; +} +void ast_channel_codec_set(struct ast_channel *chan, const char *value) +{ + ast_copy_string(chan->codec, value, sizeof(chan->codec)); +} + +rtp_statistics *ast_channel_rtpStats_get(const struct ast_channel *chan) +{ + return chan->rtp_stats; +} +void ast_channel_rtpStats_set(struct ast_channel *chan, rtp_statistics *rtp_stats) +{ + chan->rtp_stats = rtp_stats; +} + void ast_channel_callid_set(struct ast_channel *chan, ast_callid callid) { char call_identifier_from[AST_CALLID_BUFFER_LENGTH]; diff --git a/main/stasis_channels.c b/main/stasis_channels.c index 5e39c0765411b277ce40cbd563f1e0855067d80b..3cf6ff4d33470485030872291e54575dae7a6d16 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -551,6 +551,12 @@ struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *cha /* These have to be recreated as they may have changed, unfortunately */ snapshot->manager_vars = ast_channel_get_manager_vars(chan); snapshot->ari_vars = ast_channel_get_ari_vars(chan); + snapshot->sessionId = ast_channel_sessionId(chan); + ast_copy_string(snapshot->sipIpAddress, ast_channel_sipIpAddress(chan), sizeof(snapshot->sipIpAddress)); + ast_copy_string(snapshot->farEndIPAddress, ast_channel_farEndIPAddress(chan), sizeof(snapshot->farEndIPAddress)); + snapshot->sipResponseCode = ast_channel_sipResponseCode(chan); + ast_copy_string(snapshot->codec, ast_channel_codec_get(chan), sizeof(snapshot->codec)); + snapshot->rtp_stats = ast_channel_rtpStats_get(chan); return snapshot; } diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index f00519b9c67667060b543f31e75491744c0c726b..fe565f66def7b41cfac562f1371eb47ca936ca55 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -2085,6 +2085,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, SCOPE_EXIT_RTN_VALUE(1, "No channel\n"); } + ast_channel_codec_set(session->channel, ast_format_get_codec_name(ast_channel_writeformat(session->channel))); /* Ensure incoming transport is compatible with the endpoint's configuration */ if (!session->endpoint->media.rtp.use_received_transport && check_endpoint_media_transport(session->endpoint, remote_stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) { diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index da0b18b32fb145c02cdf3b67bf09a34ab28ab790..85a64da289213ee7ffc05501ce06de1b33d9cf87 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -1067,6 +1067,9 @@ static int handle_negotiated_sdp(struct ast_sip_session *session, const pjmedia_ unsigned int changed = 0; /* 0 = unchanged, 1 = new source, 2 = new topology */ SCOPE_ENTER(1, "%s\n", ast_sip_session_get_name(session)); + if (session && session->channel) + ast_channel_farEndIPAddress_set(session->channel, pj_strbuf(&remote->origin.addr), pj_strlen(&remote->origin.addr)); + if (!session->pending_media_state->topology) { if (session->active_media_state->topology) { /* @@ -2805,7 +2808,6 @@ static pj_bool_t session_reinvite_on_rx_request(pjsip_rx_data *rdata) } pjsip_rx_data_clone(rdata, 0, &session->deferred_reinvite); - return PJ_TRUE; } @@ -4073,6 +4075,11 @@ static int new_invite(struct new_invite *invite) handle_incoming_request(invite->session, invite->rdata); end: + if (invite->session && invite->session->channel) { + ast_channel_sessionId_set(invite->session->channel, local->origin.id); + ast_channel_sipIpAddress_set(invite->session->channel, pj_strbuf(&local->origin.addr), pj_strlen(&local->origin.addr)); + } + SCOPE_EXIT_RTN_VALUE(0, "%s\n", ast_sip_session_get_name(invite->session)); } @@ -4491,6 +4498,8 @@ static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_d supplement->incoming_response(session, rdata); } } + if (session && session->channel) + ast_channel_sipResponseCode_set(session->channel, status.code == 180 ? 487 : status.code); SCOPE_EXIT("%s\n", ast_sip_session_get_name(session)); } @@ -4550,6 +4559,8 @@ static void handle_outgoing_response(struct ast_sip_session *session, pjsip_tx_d supplement->outgoing_response(session, tdata); } } + if (session && session->channel) + ast_channel_sipResponseCode_set(session->channel, status.code == 180 ? 487 : status.code); SCOPE_EXIT("%s\n", ast_sip_session_get_name(session)); } @@ -5262,6 +5273,11 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru pj_strassign(&local->origin.addr, &local->conn->addr); end: + if (session && session->channel) { + ast_channel_sessionId_set(session->channel, local->origin.id); + ast_channel_sipIpAddress_set(session->channel, pj_strbuf(&local->origin.addr), pj_strlen(&local->origin.addr)); + } + SCOPE_EXIT_RTN_VALUE(local, "%s\n", ast_sip_session_get_name(session)); }