summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2014-07-31 11:57:51 +0000
committerMatthew Jordan <mjordan@digium.com>2014-07-31 11:57:51 +0000
commitbbeaeea1a3f5591ca4f2342e8a014ccf1e8bd8d9 (patch)
tree6303e34248dded3c50cd7d4c676eeb5820d1dd9e
parent922e3203a9303acbc95a334793a41e07e3f4772d (diff)
res_hep_rtcp: Add module that sends RTCP information to a Homer Server
This patch adds a new module to Asterisk, res_hep_rtcp. The module subscribes to the RTCP topics in Stasis and receives RTCP information back from the message bus. It encodes into HEPv3 packets and sends the information to the res_hep module for transmission. Using this, someone with a Homer server can get live call quality monitoring for all RTP-based channels in their Asterisk 12+ systems. In addition, there were a few bugs in the RTP engine, res_rtp_asterisk, and chan_pjsip that were uncovered by the tests written for the Asterisk Test Suite. This patch fixes the following: 1) chan_pjsip failed to set its channel unique ids on its RTP instance on outbound calls. It now does this in the appropriate location, in the serialized call callback. 2) The rtp_engine was overflowing some values when packed into JSON. Specifically, some longs and unsigned ints can't be be packed into integer values, for obvious reasons. Since libjansson only supports integers, floats, strings, booleans, and objects, we print these values into strings. 3) res_rtp_asterisk had a few problems: (a) it would emit a source IP address of 0.0.0.0 if bound to that IP address. We now use ast_find_ourip to get a better IP address, and properly marshal the result into an ast_strdupa'd string. (b) Reports can be generated with no report bodies. In particular, this occurs when a sender is transmitting information to a receiver (who will send no RTP back to the sender). As such, the sender has no report body for what it received. We now properly handle this case, and the sender will emit SR reports with no body. Likewise, if we receive an RTCP packet with no report body, we will still generate the appropriate events. ASTERISK-24119 #close ........ Merged revisions 419823 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419825 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--CHANGES5
-rw-r--r--channels/chan_pjsip.c44
-rw-r--r--main/rtp_engine.c16
-rw-r--r--res/res_hep_rtcp.c147
-rw-r--r--res/res_rtp_asterisk.c202
5 files changed, 304 insertions, 110 deletions
diff --git a/CHANGES b/CHANGES
index a8564b845..299489e8c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -245,6 +245,11 @@ res_pjsip
created for an endpoint with this setting will have its accountcode set
to the specified value.
+res_hep_rtcp
+------------------
+ * A new module, res_hep_rtcp, has been added that will forward RTCP call
+ statistics to a HEP capture server. See res_hep for more information.
+
Functions
------------------
* Function AUDIOHOOK_INHERIT has been deprecated. Audiohooks are now
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 92a96eb0e..c958f8086 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -353,6 +353,16 @@ static struct ast_rtp_glue chan_pjsip_rtp_glue = {
.update_peer = chan_pjsip_set_rtp_peer,
};
+static void set_channel_on_rtp_instance(struct chan_pjsip_pvt *pvt, const char *channel_id)
+{
+ if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) {
+ ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, channel_id);
+ }
+ if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) {
+ ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, channel_id);
+ }
+}
+
/*! \brief Function called to create a new PJSIP Asterisk channel */
static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int state, const char *exten, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
{
@@ -452,12 +462,7 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
* these will need to be recaptured as well */
pvt->media[SIP_MEDIA_AUDIO] = ao2_find(session->media, "audio", OBJ_KEY);
pvt->media[SIP_MEDIA_VIDEO] = ao2_find(session->media, "video", OBJ_KEY);
- if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) {
- ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, ast_channel_uniqueid(chan));
- }
- if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) {
- ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(chan));
- }
+ set_channel_on_rtp_instance(pvt, ast_channel_uniqueid(chan));
return chan;
}
@@ -685,12 +690,7 @@ static int fixup(void *data)
struct chan_pjsip_pvt *pvt = channel->pvt;
channel->session->channel = fix_data->chan;
- if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) {
- ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, ast_channel_uniqueid(fix_data->chan));
- }
- if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) {
- ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(fix_data->chan));
- }
+ set_channel_on_rtp_instance(pvt, ast_channel_uniqueid(fix_data->chan));
return 0;
}
@@ -1523,7 +1523,9 @@ static void update_initial_connected_line(struct ast_sip_session *session)
static int call(void *data)
{
- struct ast_sip_session *session = data;
+ struct ast_sip_channel_pvt *channel = data;
+ struct ast_sip_session *session = channel->session;
+ struct chan_pjsip_pvt *pvt = channel->pvt;
pjsip_tx_data *tdata;
int res = ast_sip_session_create_invite(session, &tdata);
@@ -1532,10 +1534,11 @@ static int call(void *data)
ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
ast_queue_hangup(session->channel);
} else {
+ set_channel_on_rtp_instance(pvt, ast_channel_uniqueid(session->channel));
update_initial_connected_line(session);
ast_sip_session_send_request(session, tdata);
}
- ao2_ref(session, -1);
+ ao2_ref(channel, -1);
return res;
}
@@ -1544,10 +1547,10 @@ static int chan_pjsip_call(struct ast_channel *ast, const char *dest, int timeou
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
- ao2_ref(channel->session, +1);
- if (ast_sip_push_task(channel->session->serializer, call, channel->session)) {
+ ao2_ref(channel, +1);
+ if (ast_sip_push_task(channel->session->serializer, call, channel)) {
ast_log(LOG_WARNING, "Error attempting to place outbound call to call '%s'\n", dest);
- ao2_cleanup(channel->session);
+ ao2_cleanup(channel);
return -1;
}
@@ -1632,12 +1635,7 @@ static struct hangup_data *hangup_data_alloc(int cause, struct ast_channel *chan
static void clear_session_and_channel(struct ast_sip_session *session, struct ast_channel *ast, struct chan_pjsip_pvt *pvt)
{
session->channel = NULL;
- if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) {
- ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, "");
- }
- if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) {
- ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, "");
- }
+ set_channel_on_rtp_instance(pvt, "");
ast_channel_tech_pvt_set(ast, NULL);
}
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 07ef1f697..52be8b90e 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -1909,13 +1909,15 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
for (i = 0; i < payload->report->reception_report_count; i++) {
struct ast_json *json_report_block;
- json_report_block = ast_json_pack("{s: i, s: i, s: i, s: i, s: i, s: i, s: i}",
+ char str_lsr[32];
+ snprintf(str_lsr, sizeof(str_lsr), "%u", payload->report->report_block[i]->lsr);
+ json_report_block = ast_json_pack("{s: i, s: i, s: i, s: i, s: i, s: s, s: i}",
"source_ssrc", payload->report->report_block[i]->source_ssrc,
"fraction_lost", payload->report->report_block[i]->lost_count.fraction,
"packets_lost", payload->report->report_block[i]->lost_count.packets,
"highest_seq_no", payload->report->report_block[i]->highest_seq_no,
"ia_jitter", payload->report->report_block[i]->ia_jitter,
- "lsr", payload->report->report_block[i]->lsr,
+ "lsr", str_lsr,
"dlsr", payload->report->report_block[i]->dlsr);
if (!json_report_block) {
return NULL;
@@ -1927,9 +1929,13 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
}
if (payload->report->type == AST_RTP_RTCP_SR) {
- json_rtcp_sender_info = ast_json_pack("{s: i, s: i, s: i, s: i, s: i}",
- "ntp_timestamp_sec", payload->report->sender_information.ntp_timestamp.tv_sec,
- "ntp_timestamp_usec", payload->report->sender_information.ntp_timestamp.tv_usec,
+ char sec[32];
+ char usec[32];
+ snprintf(sec, sizeof(sec), "%ld", payload->report->sender_information.ntp_timestamp.tv_sec);
+ snprintf(usec, sizeof(usec), "%ld", payload->report->sender_information.ntp_timestamp.tv_usec);
+ json_rtcp_sender_info = ast_json_pack("{s: s, s: s, s: i, s: i, s: i}",
+ "ntp_timestamp_sec", sec,
+ "ntp_timestamp_usec", usec,
"rtp_timestamp", payload->report->sender_information.rtp_timestamp,
"packets", payload->report->sender_information.packet_count,
"octets", payload->report->sender_information.octet_count);
diff --git a/res/res_hep_rtcp.c b/res/res_hep_rtcp.c
new file mode 100644
index 000000000..63df1c8b0
--- /dev/null
+++ b/res/res_hep_rtcp.c
@@ -0,0 +1,147 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2014, Digium, Inc.
+ *
+ * Matt Jordan <mjordan@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief RTCP logging with Homer
+ *
+ * \author Matt Jordan <mjordan@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>res_hep</depend>
+ <defaultenabled>no</defaultenabled>
+ <support_level>extended</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <pjsip.h>
+
+#include "asterisk/res_hep.h"
+#include "asterisk/module.h"
+#include "asterisk/netsock2.h"
+#include "asterisk/stasis.h"
+#include "asterisk/rtp_engine.h"
+#include "asterisk/json.h"
+#include "asterisk/config.h"
+
+static struct stasis_subscription *stasis_rtp_subscription;
+
+static void rtcp_message_handler(struct stasis_message *message)
+{
+
+ RAII_VAR(struct ast_json *, json_payload, NULL, ast_json_unref);
+ RAII_VAR(char *, payload, NULL, ast_json_free);
+ struct ast_json *json_blob;
+ struct ast_json *json_channel;
+ struct ast_json *json_rtcp;
+ struct hepv3_capture_info *capture_info;
+ struct ast_json *from;
+ struct ast_json *to;
+ struct timeval current_time = ast_tvnow();
+
+ json_payload = stasis_message_to_json(message, NULL);
+ if (!json_payload) {
+ return;
+ }
+
+ json_blob = ast_json_object_get(json_payload, "blob");
+ if (!json_blob) {
+ return;
+ }
+
+ json_channel = ast_json_object_get(json_payload, "channel");
+ if (!json_channel) {
+ return;
+ }
+
+ json_rtcp = ast_json_object_get(json_payload, "rtcp_report");
+ if (!json_rtcp) {
+ return;
+ }
+
+ from = ast_json_object_get(json_blob, "from");
+ to = ast_json_object_get(json_blob, "to");
+ if (!from || !to) {
+ return;
+ }
+
+ payload = ast_json_dump_string(json_rtcp);
+ if (ast_strlen_zero(payload)) {
+ return;
+ }
+
+ capture_info = hepv3_create_capture_info(payload, strlen(payload));
+ if (!capture_info) {
+ return;
+ }
+ ast_sockaddr_parse(&capture_info->src_addr, ast_json_string_get(from), PARSE_PORT_REQUIRE);
+ ast_sockaddr_parse(&capture_info->dst_addr, ast_json_string_get(to), PARSE_PORT_REQUIRE);
+
+ capture_info->uuid = ast_strdup(ast_json_string_get(ast_json_object_get(json_channel, "name")));
+ if (!capture_info->uuid) {
+ ao2_ref(capture_info, -1);
+ return;
+ }
+ capture_info->capture_time = current_time;
+ capture_info->capture_type = HEPV3_CAPTURE_TYPE_RTCP;
+ capture_info->zipped = 0;
+
+ hepv3_send_packet(capture_info);
+}
+
+static void rtp_topic_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message)
+{
+ struct stasis_message_type *message_type = stasis_message_type(message);
+
+ if ((message_type == ast_rtp_rtcp_sent_type()) ||
+ (message_type == ast_rtp_rtcp_received_type())) {
+ rtcp_message_handler(message);
+ }
+}
+
+static int load_module(void)
+{
+
+ stasis_rtp_subscription = stasis_subscribe(ast_rtp_topic(),
+ rtp_topic_handler, NULL);
+ if (!stasis_rtp_subscription) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+ if (stasis_rtp_subscription) {
+ stasis_rtp_subscription = stasis_unsubscribe(stasis_rtp_subscription);
+ }
+
+ return 0;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "RTCP HEPv3 Logger",
+ .load = load_module,
+ .unload = unload_module,
+ .load_pri = AST_MODPRI_DEFAULT,
+ );
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 55abf6154..f192bacb8 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -2637,10 +2637,15 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
int rate = rtp_get_rate(rtp->f.subclass.format);
int ice;
int header_offset = 0;
- struct ast_sockaddr remote_address = { {0,} };
- struct ast_rtp_rtcp_report_block *report_block;
+ char *str_remote_address;
+ char *str_local_address;
+ struct ast_sockaddr remote_address = { { 0, } };
+ struct ast_sockaddr local_address = { { 0, } };
+ struct ast_sockaddr real_remote_address = { { 0, } };
+ struct ast_sockaddr real_local_address = { { 0, } };
+ struct ast_rtp_rtcp_report_block *report_block = NULL;
RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report,
- ast_rtp_rtcp_report_alloc(1),
+ ast_rtp_rtcp_report_alloc(rtp->themssrc ? 1 : 0),
ao2_cleanup);
if (!rtp || !rtp->rtcp) {
@@ -2656,16 +2661,11 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
return 1;
}
- report_block = ast_calloc(1, sizeof(*report_block));
- if (!report_block) {
- return 1;
- }
-
/* Compute statistics */
calculate_lost_packet_statistics(rtp, &lost_packets, &fraction_lost);
gettimeofday(&now, NULL);
- rtcp_report->reception_report_count = 1;
+ rtcp_report->reception_report_count = rtp->themssrc ? 1 : 0;
rtcp_report->ssrc = rtp->ssrc;
rtcp_report->type = sr ? RTCP_PT_SR : RTCP_PT_RR;
if (sr) {
@@ -2674,17 +2674,25 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
rtcp_report->sender_information.packet_count = rtp->txcount;
rtcp_report->sender_information.octet_count = rtp->txoctetcount;
}
- rtcp_report->report_block[0] = report_block;
- report_block->source_ssrc = rtp->themssrc;
- report_block->lost_count.fraction = (fraction_lost & 0xff);
- report_block->lost_count.packets = (lost_packets & 0xffffff);
- report_block->highest_seq_no = (rtp->cycles | (rtp->lastrxseqno & 0xffff));
- report_block->ia_jitter = (unsigned int)(rtp->rxjitter * rate);
- report_block->lsr = rtp->rtcp->themrxlsr;
- /* If we haven't received an SR report, DLSR should be 0 */
- if (!ast_tvzero(rtp->rtcp->rxlsr)) {
- timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
- report_block->dlsr = (((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000;
+
+ if (rtp->themssrc) {
+ report_block = ast_calloc(1, sizeof(*report_block));
+ if (!report_block) {
+ return 1;
+ }
+
+ rtcp_report->report_block[0] = report_block;
+ report_block->source_ssrc = rtp->themssrc;
+ report_block->lost_count.fraction = (fraction_lost & 0xff);
+ report_block->lost_count.packets = (lost_packets & 0xffffff);
+ report_block->highest_seq_no = (rtp->cycles | (rtp->lastrxseqno & 0xffff));
+ report_block->ia_jitter = (unsigned int)(rtp->rxjitter * rate);
+ report_block->lsr = rtp->rtcp->themrxlsr;
+ /* If we haven't received an SR report, DLSR should be 0 */
+ if (!ast_tvzero(rtp->rtcp->rxlsr)) {
+ timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
+ report_block->dlsr = (((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000;
+ }
}
timeval2ntp(rtcp_report->sender_information.ntp_timestamp, &now_msw, &now_lsw);
rtcpheader = (unsigned int *)bdata;
@@ -2699,14 +2707,17 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
rtcpheader[6] = htonl(rtcp_report->sender_information.octet_count);
len += 20;
}
- rtcpheader[2 + header_offset] = htonl(report_block->source_ssrc); /* Their SSRC */
- rtcpheader[3 + header_offset] = htonl((report_block->lost_count.fraction << 24) | report_block->lost_count.packets);
- rtcpheader[4 + header_offset] = htonl(report_block->highest_seq_no);
- rtcpheader[5 + header_offset] = htonl(report_block->ia_jitter);
- rtcpheader[6 + header_offset] = htonl(report_block->lsr);
- rtcpheader[7 + header_offset] = htonl(report_block->dlsr);
- len += 24;
- rtcpheader[0] = htonl((2 << 30) | (1 << 24) | ((sr ? RTCP_PT_SR : RTCP_PT_RR) << 16) | ((len/4)-1));
+ if (report_block) {
+ rtcpheader[2 + header_offset] = htonl(report_block->source_ssrc); /* Their SSRC */
+ rtcpheader[3 + header_offset] = htonl((report_block->lost_count.fraction << 24) | report_block->lost_count.packets);
+ rtcpheader[4 + header_offset] = htonl(report_block->highest_seq_no);
+ rtcpheader[5 + header_offset] = htonl(report_block->ia_jitter);
+ rtcpheader[6 + header_offset] = htonl(report_block->lsr);
+ rtcpheader[7 + header_offset] = htonl(report_block->dlsr);
+ len += 24;
+ }
+ rtcpheader[0] = htonl((2 << 30) | (rtcp_report->reception_report_count << 24)
+ | ((sr ? RTCP_PT_SR : RTCP_PT_RR) << 16) | ((len/4)-1));
/* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
/* it can change mid call, and SDES can't) */
@@ -2758,8 +2769,22 @@ static int ast_rtcp_write_report(struct ast_rtp_instance *instance, int sr)
ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(report_block->dlsr / 65536.0));
}
- message_blob = ast_json_pack("{s: s}",
- "to", ast_sockaddr_stringify(&remote_address));
+ ast_rtp_instance_get_local_address(instance, &local_address);
+ if (!ast_find_ourip(&real_local_address, &local_address, 0)) {
+ str_local_address = ast_strdupa(ast_sockaddr_stringify(&real_local_address));
+ } else {
+ str_local_address = ast_strdupa(ast_sockaddr_stringify(&local_address));
+ }
+
+ if (!ast_find_ourip(&real_remote_address, &remote_address, 0)) {
+ str_remote_address = ast_strdupa(ast_sockaddr_stringify(&real_remote_address));
+ } else {
+ str_remote_address = ast_strdupa(ast_sockaddr_stringify(&remote_address));
+ }
+
+ message_blob = ast_json_pack("{s: s, s: s}",
+ "to", str_remote_address,
+ "from", str_local_address);
ast_rtp_publish_rtcp_message(instance, ast_rtp_rtcp_sent_type(),
rtcp_report,
message_blob);
@@ -3574,6 +3599,11 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
int report_counter = 0;
struct ast_rtp_rtcp_report_block *report_block;
struct ast_frame *f = &ast_null_frame;
+ char *str_local_address;
+ char *str_remote_address;
+ struct ast_sockaddr local_address = { { 0,} };
+ struct ast_sockaddr real_local_address = { { 0, } };
+ struct ast_sockaddr real_remote_address = { { 0, } };
/* Read in RTCP data from the socket */
if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET,
@@ -3630,6 +3660,8 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
ast_debug(1, "Got RTCP report of %d bytes\n", res);
+ ast_rtp_instance_get_local_address(instance, &local_address);
+
while (position < packetwords) {
int i, pt, rc;
unsigned int length;
@@ -3667,11 +3699,6 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
}
i += 2; /* Advance past header and ssrc */
- if (rc == 0 && pt == RTCP_PT_RR) {
- /* We're receiving a receiver report with no reports, which is ok */
- position += (length + 1);
- continue;
- }
switch (pt) {
case RTCP_PT_SR:
gettimeofday(&rtp->rtcp->rxlsr, NULL);
@@ -3696,64 +3723,75 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
rtcp_report->sender_information.octet_count);
}
i += 5;
- if (rc < 1) {
- break;
- }
/* Intentional fall through */
case RTCP_PT_RR:
if (rtcp_report->type != RTCP_PT_SR) {
rtcp_report->type = RTCP_PT_RR;
}
- /* Don't handle multiple reception reports (rc > 1) yet */
- report_block = ast_calloc(1, sizeof(*report_block));
- if (!report_block) {
- return &ast_null_frame;
+ if (rc > 0) {
+ /* Don't handle multiple reception reports (rc > 1) yet */
+ report_block = ast_calloc(1, sizeof(*report_block));
+ if (!report_block) {
+ return &ast_null_frame;
+ }
+ rtcp_report->report_block[report_counter] = report_block;
+ report_block->source_ssrc = ntohl(rtcpheader[i]);
+ report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff;
+ report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24);
+ report_block->highest_seq_no = ntohl(rtcpheader[i + 2]);
+ report_block->ia_jitter = ntohl(rtcpheader[i + 3]);
+ report_block->lsr = ntohl(rtcpheader[i + 4]);
+ report_block->dlsr = ntohl(rtcpheader[i + 5]);
+ if (report_block->lsr
+ && update_rtt_stats(rtp, report_block->lsr, report_block->dlsr)
+ && rtcp_debug_test_addr(&addr)) {
+ struct timeval now;
+ unsigned int lsr_now, lsw, msw;
+ gettimeofday(&now, NULL);
+ timeval2ntp(now, &msw, &lsw);
+ lsr_now = (((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16));
+ ast_verbose("Internal RTCP NTP clock skew detected: "
+ "lsr=%u, now=%u, dlsr=%u (%u:%03ums), "
+ "diff=%u\n",
+ report_block->lsr, lsr_now, report_block->dlsr, report_block->dlsr / 65536,
+ (report_block->dlsr % 65536) * 1000 / 65536,
+ report_block->dlsr - (lsr_now - report_block->lsr));
+ }
+ update_jitter_stats(rtp, report_block->ia_jitter);
+ update_lost_stats(rtp, report_block->lost_count.packets);
+ rtp->rtcp->reported_jitter_count++;
+
+ if (rtcp_debug_test_addr(&addr)) {
+ ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
+ ast_verbose(" Packets lost so far: %u\n", report_block->lost_count.packets);
+ ast_verbose(" Highest sequence number: %u\n", report_block->highest_seq_no & 0x0000ffff);
+ ast_verbose(" Sequence number cycles: %u\n", report_block->highest_seq_no >> 16);
+ ast_verbose(" Interarrival jitter: %u\n", report_block->ia_jitter);
+ ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long)(report_block->lsr) >> 16,((unsigned long)(report_block->lsr) << 16) * 4096);
+ ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0);
+ ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt);
+ }
+ report_counter++;
}
- rtcp_report->report_block[report_counter] = report_block;
- report_block->source_ssrc = ntohl(rtcpheader[i]);
- report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff;
- report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24);
- report_block->highest_seq_no = ntohl(rtcpheader[i + 2]);
- report_block->ia_jitter = ntohl(rtcpheader[i + 3]);
- report_block->lsr = ntohl(rtcpheader[i + 4]);
- report_block->dlsr = ntohl(rtcpheader[i + 5]);
- if (report_block->lsr
- && update_rtt_stats(rtp, report_block->lsr, report_block->dlsr)
- && rtcp_debug_test_addr(&addr)) {
- struct timeval now;
- unsigned int lsr_now, lsw, msw;
- gettimeofday(&now, NULL);
- timeval2ntp(now, &msw, &lsw);
- lsr_now = (((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16));
- ast_verbose("Internal RTCP NTP clock skew detected: "
- "lsr=%u, now=%u, dlsr=%u (%u:%03ums), "
- "diff=%u\n",
- report_block->lsr, lsr_now, report_block->dlsr, report_block->dlsr / 65536,
- (report_block->dlsr % 65536) * 1000 / 65536,
- report_block->dlsr - (lsr_now - report_block->lsr));
+ /* If and when we handle more than one report block, this should occur outside
+ * this loop.
+ */
+ if (!ast_find_ourip(&real_local_address, &local_address, 0)) {
+ str_local_address = ast_strdupa(ast_sockaddr_stringify(&real_local_address));
+ } else {
+ str_local_address = ast_strdupa(ast_sockaddr_stringify(&local_address));
}
- update_jitter_stats(rtp, report_block->ia_jitter);
- update_lost_stats(rtp, report_block->lost_count.packets);
- rtp->rtcp->reported_jitter_count++;
- if (rtcp_debug_test_addr(&addr)) {
- ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
- ast_verbose(" Packets lost so far: %u\n", report_block->lost_count.packets);
- ast_verbose(" Highest sequence number: %u\n", report_block->highest_seq_no & 0x0000ffff);
- ast_verbose(" Sequence number cycles: %u\n", report_block->highest_seq_no >> 16);
- ast_verbose(" Interarrival jitter: %u\n", report_block->ia_jitter);
- ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long)(report_block->lsr) >> 16,((unsigned long)(report_block->lsr) << 16) * 4096);
- ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0);
- ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt);
+ if (!ast_find_ourip(&real_remote_address, &addr, 0)) {
+ str_remote_address = ast_strdupa(ast_sockaddr_stringify(&real_remote_address));
+ } else {
+ str_remote_address = ast_strdupa(ast_sockaddr_stringify(&addr));
}
- report_counter++;
- /* If and when we handle more than one report block, this should occur outside
- * this loop.
- */
- message_blob = ast_json_pack("{s: s, s: f}",
- "from", ast_sockaddr_stringify(&addr),
+ message_blob = ast_json_pack("{s: s, s: s, s: f}",
+ "from", str_remote_address,
+ "to", str_local_address,
"rtt", rtp->rtcp->rtt);
ast_rtp_publish_rtcp_message(instance, ast_rtp_rtcp_received_type(),
rtcp_report,