mgcp/rtp: Add RTP header patch mode configuration
This adds datastructures and a VTY frontend to configure the different type of RTP header patching: SSRC and timestamp. Note that timestamp patching is not yet implemented. Sponsored-by: On-Waves ehf
This commit is contained in:
parent
55ba140da1
commit
db2d431697
|
@ -118,6 +118,10 @@ struct mgcp_trunk_config {
|
|||
|
||||
int omit_rtcp;
|
||||
|
||||
/* RTP patching */
|
||||
int force_constant_ssrc; /* 0: don't, 1: once */
|
||||
int force_constant_timing;
|
||||
|
||||
/* spec handling */
|
||||
int force_realloc;
|
||||
|
||||
|
|
|
@ -83,6 +83,10 @@ struct mgcp_rtp_end {
|
|||
int frames_per_packet;
|
||||
char *fmtp_extra;
|
||||
|
||||
/* RTP patching */
|
||||
int force_constant_ssrc;
|
||||
int force_constant_timing;
|
||||
|
||||
/*
|
||||
* Each end has a socket...
|
||||
*/
|
||||
|
@ -142,9 +146,6 @@ struct mgcp_endpoint {
|
|||
struct mgcp_rtp_state net_state;
|
||||
struct mgcp_rtp_state bts_state;
|
||||
|
||||
/* SSRC/seq/ts patching for loop */
|
||||
int allow_patch;
|
||||
|
||||
/* fields for re-transmission */
|
||||
char *last_trans;
|
||||
char *last_response;
|
||||
|
@ -176,6 +177,9 @@ static inline int endp_back_channel(int endpoint)
|
|||
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
|
||||
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
|
||||
|
||||
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
|
||||
struct mgcp_rtp_end *rtp);
|
||||
|
||||
void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
|
||||
uint32_t *expected, int *loss);
|
||||
uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
|
||||
|
|
|
@ -264,7 +264,7 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta
|
|||
state->seq_offset = (state->out_stream.last_seq + 1) - seq;
|
||||
state->timestamp_offset =
|
||||
(state->out_stream.last_timestamp + tsdelta) - timestamp;
|
||||
state->patch = endp->allow_patch;
|
||||
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",
|
||||
|
|
|
@ -614,6 +614,21 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
|
|||
return found_media;
|
||||
}
|
||||
|
||||
void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
|
||||
struct mgcp_rtp_end *rtp)
|
||||
{
|
||||
struct mgcp_trunk_config *tcfg = endp->tcfg;
|
||||
|
||||
rtp->force_constant_timing = tcfg->force_constant_timing;
|
||||
rtp->force_constant_ssrc = tcfg->force_constant_ssrc;
|
||||
|
||||
LOGP(DMGCP, LOGL_DEBUG,
|
||||
"Configuring RTP endpoint: local port %d%s%s\n",
|
||||
ntohs(rtp->rtp_port),
|
||||
rtp->force_constant_timing ? ", force constant timing" : "",
|
||||
rtp->force_constant_ssrc ? ", force constant ssrc" : "");
|
||||
}
|
||||
|
||||
static struct msgb *handle_create_con(struct mgcp_parse_data *p)
|
||||
{
|
||||
struct mgcp_trunk_config *tcfg;
|
||||
|
@ -688,6 +703,8 @@ mgcp_header_done:
|
|||
|
||||
/* initialize */
|
||||
endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0;
|
||||
mgcp_rtp_end_config(endp, 0, &endp->net_end);
|
||||
mgcp_rtp_end_config(endp, 0, &endp->bts_end);
|
||||
|
||||
/* set to zero until we get the info */
|
||||
memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr));
|
||||
|
@ -825,6 +842,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));
|
||||
|
@ -1121,7 +1141,6 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
|
|||
memset(&endp->bts_state, 0, sizeof(endp->bts_state));
|
||||
|
||||
endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE;
|
||||
endp->allow_patch = 0;
|
||||
|
||||
memset(&endp->taps, 0, sizeof(endp->taps));
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
|
||||
#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
|
||||
|
||||
static struct mgcp_config *g_cfg = NULL;
|
||||
|
||||
|
@ -88,6 +89,13 @@ static int config_write_mgcp(struct vty *vty)
|
|||
vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
|
||||
if (g_cfg->trunk.force_constant_ssrc || g_cfg->trunk.force_constant_timing) {
|
||||
vty_out(vty, " %srtp-patch ssrc%s",
|
||||
g_cfg->trunk.force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
|
||||
vty_out(vty, " %srtp-patch timestamp%s",
|
||||
g_cfg->trunk.force_constant_timing ? "" : "no ", VTY_NEWLINE);
|
||||
} else
|
||||
vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
|
||||
if (g_cfg->trunk.audio_payload != -1)
|
||||
vty_out(vty, " sdp audio-payload number %d%s",
|
||||
g_cfg->trunk.audio_payload, VTY_NEWLINE);
|
||||
|
@ -421,6 +429,61 @@ DEFUN(cfg_mgcp_no_omit_rtcp,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_patch_rtp_ssrc,
|
||||
cfg_mgcp_patch_rtp_ssrc_cmd,
|
||||
"rtp-patch ssrc",
|
||||
RTP_PATCH_STR
|
||||
"Force a fixed SSRC\n"
|
||||
)
|
||||
{
|
||||
g_cfg->trunk.force_constant_ssrc = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
|
||||
cfg_mgcp_no_patch_rtp_ssrc_cmd,
|
||||
"no rtp-patch ssrc",
|
||||
NO_STR RTP_PATCH_STR
|
||||
"Force a fixed SSRC\n"
|
||||
)
|
||||
{
|
||||
g_cfg->trunk.force_constant_ssrc = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_patch_rtp_ts,
|
||||
cfg_mgcp_patch_rtp_ts_cmd,
|
||||
"rtp-patch timestamp",
|
||||
RTP_PATCH_STR
|
||||
"Adjust RTP timestamp\n"
|
||||
)
|
||||
{
|
||||
g_cfg->trunk.force_constant_timing = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_patch_rtp_ts,
|
||||
cfg_mgcp_no_patch_rtp_ts_cmd,
|
||||
"no rtp-patch timestamp",
|
||||
NO_STR RTP_PATCH_STR
|
||||
"Adjust RTP timestamp\n"
|
||||
)
|
||||
{
|
||||
g_cfg->trunk.force_constant_timing = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_mgcp_no_patch_rtp,
|
||||
cfg_mgcp_no_patch_rtp_cmd,
|
||||
"no rtp-patch",
|
||||
NO_STR RTP_PATCH_STR)
|
||||
{
|
||||
g_cfg->trunk.force_constant_ssrc = 0;
|
||||
g_cfg->trunk.force_constant_timing = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define CALL_AGENT_STR "Callagent information\n"
|
||||
DEFUN(cfg_mgcp_agent_addr,
|
||||
cfg_mgcp_agent_addr_cmd,
|
||||
|
@ -511,6 +574,13 @@ static int config_write_trunk(struct vty *vty)
|
|||
vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
|
||||
if (trunk->force_constant_ssrc || trunk->force_constant_timing) {
|
||||
vty_out(vty, " %srtp-patch ssrc%s",
|
||||
trunk->force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
|
||||
vty_out(vty, " %srtp-patch timestamp%s",
|
||||
trunk->force_constant_timing ? "" : "no ", VTY_NEWLINE);
|
||||
} else
|
||||
vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
|
||||
if (trunk->audio_fmtp_extra)
|
||||
vty_out(vty, " sdp audio fmtp-extra %s%s",
|
||||
trunk->audio_fmtp_extra, VTY_NEWLINE);
|
||||
|
@ -599,6 +669,66 @@ DEFUN(cfg_trunk_no_omit_rtcp,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_patch_rtp_ssrc,
|
||||
cfg_trunk_patch_rtp_ssrc_cmd,
|
||||
"rtp-patch ssrc",
|
||||
RTP_PATCH_STR
|
||||
"Force a fixed SSRC\n"
|
||||
)
|
||||
{
|
||||
struct mgcp_trunk_config *trunk = vty->index;
|
||||
trunk->force_constant_ssrc = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_patch_rtp_ssrc,
|
||||
cfg_trunk_no_patch_rtp_ssrc_cmd,
|
||||
"no rtp-patch ssrc",
|
||||
NO_STR RTP_PATCH_STR
|
||||
"Force a fixed SSRC\n"
|
||||
)
|
||||
{
|
||||
struct mgcp_trunk_config *trunk = vty->index;
|
||||
trunk->force_constant_ssrc = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_patch_rtp_ts,
|
||||
cfg_trunk_patch_rtp_ts_cmd,
|
||||
"rtp-patch timestamp",
|
||||
RTP_PATCH_STR
|
||||
"Adjust RTP timestamp\n"
|
||||
)
|
||||
{
|
||||
struct mgcp_trunk_config *trunk = vty->index;
|
||||
trunk->force_constant_timing = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_patch_rtp_ts,
|
||||
cfg_trunk_no_patch_rtp_ts_cmd,
|
||||
"no rtp-patch timestamp",
|
||||
NO_STR RTP_PATCH_STR
|
||||
"Adjust RTP timestamp\n"
|
||||
)
|
||||
{
|
||||
struct mgcp_trunk_config *trunk = vty->index;
|
||||
trunk->force_constant_timing = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_trunk_no_patch_rtp,
|
||||
cfg_trunk_no_patch_rtp_cmd,
|
||||
"no rtp-patch",
|
||||
NO_STR RTP_PATCH_STR)
|
||||
{
|
||||
struct mgcp_trunk_config *trunk = vty->index;
|
||||
trunk->force_constant_ssrc = 0;
|
||||
trunk->force_constant_timing = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN(loop_endp,
|
||||
loop_endp_cmd,
|
||||
"loop-endpoint <0-64> NAME (0|1)",
|
||||
|
@ -636,7 +766,10 @@ DEFUN(loop_endp,
|
|||
endp->conn_mode = MGCP_CONN_LOOPBACK;
|
||||
else
|
||||
endp->conn_mode = endp->orig_mode;
|
||||
endp->allow_patch = 1;
|
||||
|
||||
/* Handle it like a MDCX, switch on SSRC patching if enabled */
|
||||
mgcp_rtp_end_config(endp, 1, &endp->bts_end);
|
||||
mgcp_rtp_end_config(endp, 1, &endp->net_end);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
@ -827,6 +960,11 @@ int mgcp_vty_init(void)
|
|||
install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
|
||||
install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
|
||||
|
||||
install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
|
||||
|
@ -839,6 +977,11 @@ int mgcp_vty_init(void)
|
|||
install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
|
||||
install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -558,6 +558,9 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
|
|||
|
||||
trunk.number_endpoints = 1;
|
||||
trunk.endpoints = &endp;
|
||||
trunk.force_constant_ssrc = patch_ssrc;
|
||||
trunk.force_constant_timing = patch_ts;
|
||||
|
||||
endp.tcfg = &trunk;
|
||||
|
||||
/* This doesn't free endp but resets/frees all fields of the structure
|
||||
|
@ -568,7 +571,6 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
|
|||
mgcp_free_endp(&endp);
|
||||
|
||||
rtp->payload_type = 98;
|
||||
endp.allow_patch = patch_ssrc;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) {
|
||||
struct rtp_packet_info *info = test_rtp_packets1 + i;
|
||||
|
@ -577,6 +579,8 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
|
|||
OSMO_ASSERT(info->len >= 0);
|
||||
memmove(buffer, info->data, info->len);
|
||||
|
||||
mgcp_rtp_end_config(&endp, 1, rtp);
|
||||
|
||||
mgcp_patch_and_count(&endp, &state, rtp, &addr,
|
||||
buffer, info->len);
|
||||
|
||||
|
|
Loading…
Reference in New Issue