The ssrc has been used without respect to proper byte ordering. The
timestap_offset and seq_offset variables has been set even when
patching was not allowed.
This patch introduces a new variable 'ssrc' that takes the value of
the SSRC in proper byte order. The offsets in the state are only
updated if SSRC patching is allowed.
Sponsored-by: On-Waves ehf
---
openbsc/include/openbsc/mgcp_internal.h | 1 +
openbsc/src/libmgcp/mgcp_network.c | 73 ++++++++++++++++++++-----------
openbsc/src/libmgcp/mgcp_protocol.c | 3 ++
3 files changed, 52 insertions(+), 25 deletions(-)
diff --git a/openbsc/include/openbsc/mgcp_internal.h
b/openbsc/include/openbsc/mgcp_internal.h
index 02e193d..b16bd49 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -59,6 +59,7 @@ struct mgcp_rtp_state {
int cycles;
int32_t timestamp_offset;
+ uint32_t packet_duration;
uint32_t jitter;
int32_t transit;
diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c
index ce4e1d3..137ddba 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -216,7 +216,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct
mgcp_rtp_state *sta
uint32_t arrival_time;
int32_t transit, d;
uint16_t seq, udelta;
- uint32_t timestamp;
+ uint32_t timestamp, ssrc;
struct rtp_hdr *rtp_hdr;
int payload = rtp_end->payload_type;
@@ -227,31 +227,43 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct
mgcp_rtp_state *sta
seq = ntohs(rtp_hdr->sequence);
timestamp = ntohl(rtp_hdr->timestamp);
arrival_time = get_current_ts();
+ ssrc = ntohl(rtp_hdr->ssrc);
if (!state->initialized) {
state->in_stream.last_seq = seq - 1;
- state->in_stream.ssrc = state->orig_ssrc = rtp_hdr->ssrc;
+ state->in_stream.ssrc = state->orig_ssrc = ssrc;
state->in_stream.last_tsdelta = 0;
state->base_seq = seq;
state->initialized = 1;
state->jitter = 0;
state->transit = arrival_time - timestamp;
+ state->packet_duration =
+ rtp_end->rate * rtp_end->frames_per_packet *
+ rtp_end->frame_duration_num /
+ rtp_end->frame_duration_den;
state->out_stream = state->in_stream;
state->out_stream.last_timestamp = timestamp;
- state->out_stream.ssrc = rtp_hdr->ssrc - 1; /* SSRC change <=>
initialisation */
+ state->out_stream.ssrc = ssrc - 1; /* SSRC change <=> initialisation */
LOGP(DMGCP, LOGL_INFO,
"Initializing stream on 0x%x SSRC: %u timestamp: %u "
+ "pkt-duration: %d, from %s:%d in %d\n",
+ ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
+ state->seq_offset, state->packet_duration,
+ inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+ endp->conn_mode);
+ } else if (state->in_stream.ssrc != ssrc) {
+ int32_t tsdelta;
+
+ LOGP(DMGCP, LOGL_NOTICE,
+ "The SSRC changed on 0x%x SSRC: %u "
"from %s:%d in %d\n",
ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
- state->seq_offset,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
endp->conn_mode);
- } else if (state->in_stream.ssrc != rtp_hdr->ssrc) {
- int32_t tsdelta = state->out_stream.last_tsdelta;
+
+ tsdelta = state->out_stream.last_tsdelta;
if (tsdelta == 0) {
- tsdelta = rtp_end->rate * rtp_end->frames_per_packet *
- rtp_end->frame_duration_num /
- rtp_end->frame_duration_den;
+ tsdelta = state->packet_duration;
LOGP(DMGCP, LOGL_NOTICE,
"Computed timestamp delta %d based on "
"rate %d, num frames %d, frame duration %d/%d\n",
@@ -259,18 +271,25 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct
mgcp_rtp_state *sta
rtp_end->frame_duration_num,
rtp_end->frame_duration_den);
}
- state->in_stream.ssrc = rtp_hdr->ssrc;
- state->seq_offset = (state->out_stream.last_seq + 1) - seq;
- state->timestamp_offset =
- (state->out_stream.last_timestamp + tsdelta) - timestamp;
- state->patch = rtp_end->force_constant_ssrc;
- LOGP(DMGCP, LOGL_NOTICE,
- "The SSRC changed on 0x%x SSRC: %u offset: %d tsdelta: %d "
- "from %s:%d in %d\n",
- ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
- state->seq_offset, tsdelta,
- inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
- endp->conn_mode);
+ state->in_stream.ssrc = ssrc;
+ if (rtp_end->force_constant_ssrc) {
+ state->seq_offset =
+ (state->out_stream.last_seq + 1) - seq;
+ state->timestamp_offset =
+ (state->out_stream.last_timestamp + tsdelta) -
+ timestamp;
+ state->patch = 1;
+ ssrc = state->orig_ssrc;
+
+ LOGP(DMGCP, LOGL_NOTICE,
+ "SSRC patching enabled on 0x%x SSRC: %u "
+ "offset: %d tsdelta: %d "
+ "from %s:%d in %d\n",
+ ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
+ state->seq_offset, tsdelta,
+ inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+ endp->conn_mode);
+ }
state->in_stream.last_tsdelta = 0;
} else {
@@ -278,6 +297,9 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct
mgcp_rtp_state *sta
check_rtp_timestamp(endp, &state->in_stream, rtp_end, addr,
seq, timestamp, "input",
&state->in_stream.last_tsdelta);
+
+ if (state->patch)
+ ssrc = state->orig_ssrc;
}
/* Save before patching */
@@ -288,14 +310,15 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct
mgcp_rtp_state *sta
if (state->patch) {
seq += state->seq_offset;
rtp_hdr->sequence = htons(seq);
- rtp_hdr->ssrc = state->orig_ssrc;
+ rtp_hdr->ssrc = htonl(ssrc);
timestamp += state->timestamp_offset;
rtp_hdr->timestamp = htonl(timestamp);
- }
+ } else
+ ssrc = ntohl(rtp_hdr->ssrc);
/* Check again, whether the timestamps are still valid */
- if (state->out_stream.ssrc == rtp_hdr->ssrc)
+ if (state->out_stream.ssrc == ssrc)
check_rtp_timestamp(endp, &state->out_stream, rtp_end, addr,
seq, timestamp, "output",
&state->out_stream.last_tsdelta);
@@ -332,7 +355,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct
mgcp_rtp_state *sta
/* Save output values */
state->out_stream.last_seq = seq;
state->out_stream.last_timestamp = timestamp;
- state->out_stream.ssrc = rtp_hdr->ssrc;
+ state->out_stream.ssrc = ssrc;
if (payload < 0)
return;
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 6d31ace..8693396 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -834,6 +834,9 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
}
}
+ mgcp_rtp_end_config(endp, 1, &endp->net_end);
+ mgcp_rtp_end_config(endp, 1, &endp->bts_end);
+
/* modify */
LOGP(DMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n",
ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr),
ntohs(endp->net_end.rtp_port));
--
1.7.9.5