diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c index bf4629e8dd8cd1d4fd19c012372fbc743e9d781b..9eb146a7f473ec4a3d10899e06ad8cc049022385 100644 --- a/channels/chan_brcm.c +++ b/channels/chan_brcm.c @@ -85,6 +85,7 @@ static int brcm_stop_conference(struct brcm_subchannel *p); static int brcm_finish_transfer(struct ast_channel *owner, struct brcm_subchannel *p, int result); static int brcm_call(struct ast_channel *ast, const char *dest, int timeout); static int brcm_hangup(struct ast_channel *ast); +static int brcm_getRtpStats(struct ast_channel *ast); static int brcm_answer(struct ast_channel *ast); static struct ast_frame *brcm_read(struct ast_channel *ast); static int brcm_write(struct ast_channel *ast, struct ast_frame *frame); @@ -136,7 +137,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; @@ -327,6 +328,7 @@ static struct ast_channel_tech brcm_tech = { .read = brcm_read, //Channel is locked .write = brcm_write, //Channel is locked .send_digit_begin = brcm_senddigit_begin, //Channel is NOT locked + .getRtpStats = brcm_getRtpStats, //Channel is NOT locked .send_digit_end = brcm_senddigit_end, //Channel is NOT locked .indicate = brcm_indicate, //Channel is locked .transfer = brcm_transfer // Channel is locked @@ -618,6 +620,28 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat return res; } +static int brcm_getRtpStats(struct ast_channel *ast) +{ + struct brcm_subchannel *sub; + + sub = ast_channel_tech_pvt(ast); + if (!sub) { + ast_log(LOG_ERROR, "Failed to get peer subchannel\n"); + return -1; + } + + pvt_lock(sub->parent, "brcm_getRtpStats"); + if (sub->parent) { + if (endpt_get_rtp_stats(sub->parent->line_id)) { + ast_log(LOG_WARNING, "Unable to get RTP statistics\n"); + } + ast_channel_rtpStats_set(ast, &sub->rtp_stats); + } + pvt_unlock(sub->parent); + + return 0; +} + static int brcm_transfer(struct ast_channel *ast, const char *newdest) { struct brcm_pvt *pvt; @@ -894,11 +918,6 @@ static int brcm_hangup(struct ast_channel *ast) sub->conf_timer_id = -1; } - if (endpt_get_rtp_stats(p->line_id)) { - 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 && @@ -2488,6 +2507,9 @@ static void *brcm_process_event(struct endpt_event *ev) { if (sub->channel_state == OFFHOOK || sub->channel_state == AWAITONHOOK) { /* Received EVENT_ONHOOK in state OFFHOOK/AWAITONHOOK, stop dial/congestion tone */ brcm_stop_dialtone(p); + } else if (sub->channel_state == RINGBACK) { + /* Outgoing unanswered call - rtp stats need to be collected */ + brcm_getRtpStats(owner); } sub->channel_state = ONHOOK; @@ -3429,6 +3451,7 @@ static const struct blobmsg_policy endpt_count_policy[__MAX_ENDPOINTS] = { }; enum { + RTP_STATS_LINE_ID, RTP_STATS_LOCAL_BURST_DENSITY, RTP_STATS_REMOTE_BURST_DENSITY, RTP_STATS_LOCAL_BURST_DURATION, @@ -3457,6 +3480,7 @@ enum { }; static const struct blobmsg_policy endpt_rtp_stats_policy[__MAX_RTP_STATS] = { + [RTP_STATS_LINE_ID] = { .name = "lineId", .type = BLOBMSG_TYPE_INT16 }, [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 }, @@ -3549,58 +3573,76 @@ static int endpt_get_count(void) { static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struct blob_attr *msg) { struct blob_attr *tb[__MAX_RTP_STATS]; + uint16_t lineId = 0; + struct brcm_pvt *p = NULL; + struct brcm_subchannel *sub = NULL; ast_log(LOG_DEBUG, "thread %d: got answer from endptmngr on rtp_stats ubus call.\n", ast_get_tid()); blobmsg_parse(endpt_rtp_stats_policy, __MAX_RTP_STATS, tb, blob_data(msg), blob_len(msg)); + if (tb[RTP_STATS_LINE_ID]) + lineId = blobmsg_get_u16(tb[RTP_STATS_LINE_ID]); + + p = brcm_get_pvt_from_lineid(iflist, lineId); + if (!p) { + ast_log(LOG_ERROR, "No pvt with the line_id %d found!\n", lineId); + return; + } + + sub = brcm_get_active_subchannel(p); + if (!sub) { + ast_log(LOG_ERROR, "No active subchannel to write rtp stats!\n"); + return; + } + if (tb[RTP_STATS_LOCAL_BURST_DENSITY]) - rtp_stats.localBurstDensity = blobmsg_get_u16(tb[RTP_STATS_LOCAL_BURST_DENSITY]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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]); + sub->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" @@ -3609,13 +3651,13 @@ static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struc "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); + sub->rtp_stats.localBurstDensity, sub->rtp_stats.remoteBurstDensity, sub->rtp_stats.localBurstDuration, + sub->rtp_stats.remoteBurstDuration, sub->rtp_stats.localGapDensity, sub->rtp_stats.remoteGapDensity, + sub->rtp_stats.localGapDuration, sub->rtp_stats.remoteGapDuration, sub->rtp_stats.localJbRate, + sub->rtp_stats.remoteJbRate, sub->rtp_stats.localJbMax, sub->rtp_stats.remoteJbMax, sub->rtp_stats.localJbNominal, + sub->rtp_stats.remoteJbNominal, sub->rtp_stats.localJbAbsMax, sub->rtp_stats.remoteJbAbsMax, sub->rtp_stats.discarded, + sub->rtp_stats.lost, sub->rtp_stats.rxpkts, sub->rtp_stats.txpkts, sub->rtp_stats.jbAvg, sub->rtp_stats.jitter, + sub->rtp_stats.uLossRate, sub->rtp_stats.maxJitter); } static int endpt_get_rtp_stats(int line) { @@ -3623,13 +3665,26 @@ static int endpt_get_rtp_stats(int line) { struct blob_buf bb; struct ubus_request *req; int ret; + struct brcm_pvt *p = NULL; + struct brcm_subchannel *sub = NULL; /* * Reset rtp_stats first because ubus_call_answer_rtp_stats() will not be called if "ubus call endpt rtp_stats" fails, * e.g. an unanswered incoming call on which the connection is not created. In this case, all RTP statistics counters * shall be zeros. */ - memset(&rtp_stats, 0, sizeof(rtp_stats)); + p = brcm_get_pvt_from_lineid(iflist, line); + if (!p) { + ast_log(LOG_ERROR, "No pvt with the line %d found!\n", line); + return -1; + } + + sub = brcm_get_active_subchannel(p); + if (!sub) { + ast_log(LOG_ERROR, "No active subchannel to get rtp stats!\n"); + return -1; + } + memset(&sub->rtp_stats, 0, sizeof(sub->rtp_stats)); if (!endpt_id) { return -1; diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h index 5e1eca20d0733d234b886497c4aaaf48d4b84cc6..33a7da3fa1bc6fe355efea4ac6150bfee564cc50 100644 --- a/channels/chan_brcm.h +++ b/channels/chan_brcm.h @@ -111,7 +111,8 @@ struct brcm_subchannel { int onhold_hangup_timer_id; /* Current onhold hangup timer id, -1 if no active timer */ int conference_initiator; /* True if this subchannel is the original leg in a 3-way conference */ char *conference_id; /* uuid of the conference initiated by this subchannel */ - int conf_timer_id; /* Current conference call timer id, -1 if no active timer */ + int conf_timer_id; /* Current conference call timer id, -1 if no active timer */ + rtp_statistics rtp_stats; /* RTP statistics for currently hanging up channel */ };