mgcp: Update to the latest code drop.
This commit is contained in:
parent
73cdc5fd97
commit
d86208d1ed
|
@ -29,6 +29,7 @@
|
|||
#include <arpa/inet.h>
|
||||
|
||||
#define RTP_PORT_DEFAULT 4000
|
||||
|
||||
/**
|
||||
* Calculate the RTP audio port for the given multiplex
|
||||
* and the direction. This allows a semi static endpoint
|
||||
|
@ -79,14 +80,13 @@ typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, con
|
|||
typedef int (*mgcp_reset)(struct mgcp_config *cfg);
|
||||
|
||||
struct mgcp_config {
|
||||
/* common configuration */
|
||||
int source_port;
|
||||
char *local_ip;
|
||||
char *source_addr;
|
||||
unsigned int number_endpoints;
|
||||
char *bts_ip;
|
||||
char *call_agent_addr;
|
||||
|
||||
/* default endpoint data */
|
||||
struct in_addr bts_in;
|
||||
char *audio_name;
|
||||
int audio_payload;
|
||||
|
@ -95,24 +95,19 @@ struct mgcp_config {
|
|||
int rtp_base_port;
|
||||
int endp_dscp;
|
||||
|
||||
/* only used in forward mode */
|
||||
char *forward_ip;
|
||||
int forward_port;
|
||||
|
||||
unsigned int last_call_id;
|
||||
|
||||
/* endpoint configuration */
|
||||
unsigned int number_endpoints;
|
||||
struct mgcp_endpoint *endpoints;
|
||||
|
||||
/* spec handling */
|
||||
int force_realloc;
|
||||
|
||||
/* callback functionality */
|
||||
mgcp_change change_cb;
|
||||
mgcp_policy policy_cb;
|
||||
mgcp_reset reset_cb;
|
||||
void *data;
|
||||
|
||||
struct mgcp_endpoint *endpoints;
|
||||
unsigned int last_call_id;
|
||||
};
|
||||
|
||||
/* config management */
|
||||
|
|
|
@ -33,6 +33,20 @@ enum mgcp_connection_mode {
|
|||
MGCP_CONN_RECV_ONLY = 1,
|
||||
MGCP_CONN_SEND_ONLY = 2,
|
||||
MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
|
||||
MGCP_CONN_LOOPBACK = 4,
|
||||
};
|
||||
|
||||
struct mgcp_rtp_state {
|
||||
int initialized;
|
||||
int patch;
|
||||
|
||||
uint32_t orig_ssrc;
|
||||
uint32_t ssrc;
|
||||
uint16_t seq_no;
|
||||
int lost_no;
|
||||
int seq_offset;
|
||||
uint32_t last_timestamp;
|
||||
int32_t timestamp_offset;
|
||||
};
|
||||
|
||||
struct mgcp_endpoint {
|
||||
|
@ -40,6 +54,7 @@ struct mgcp_endpoint {
|
|||
char *callid;
|
||||
char *local_options;
|
||||
int conn_mode;
|
||||
int orig_mode;
|
||||
|
||||
int bts_payload_type;
|
||||
int net_payload_type;
|
||||
|
@ -68,6 +83,10 @@ struct mgcp_endpoint {
|
|||
/* statistics */
|
||||
unsigned int in_bts;
|
||||
unsigned int in_remote;
|
||||
|
||||
/* sequence bits */
|
||||
struct mgcp_rtp_state net_state;
|
||||
struct mgcp_rtp_state bts_state;
|
||||
};
|
||||
|
||||
#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
|
||||
|
|
|
@ -96,17 +96,53 @@ int mgcp_send_dummy(struct mgcp_endpoint *endp)
|
|||
endp->net_rtp, buf, 1);
|
||||
}
|
||||
|
||||
static void patch_payload(int payload, char *data, int len)
|
||||
static void patch_and_count(struct mgcp_rtp_state *state, int payload, char *data, int len)
|
||||
{
|
||||
uint16_t seq;
|
||||
uint32_t timestamp;
|
||||
struct rtp_hdr *rtp_hdr;
|
||||
|
||||
if (len < sizeof(*rtp_hdr))
|
||||
return;
|
||||
|
||||
rtp_hdr = (struct rtp_hdr *) data;
|
||||
seq = ntohs(rtp_hdr->sequence);
|
||||
timestamp = ntohl(rtp_hdr->timestamp);
|
||||
|
||||
if (!state->initialized) {
|
||||
state->seq_no = seq - 1;
|
||||
state->ssrc = state->orig_ssrc = rtp_hdr->ssrc;
|
||||
state->initialized = 1;
|
||||
state->last_timestamp = timestamp;
|
||||
} else if (state->ssrc != rtp_hdr->ssrc) {
|
||||
state->ssrc = rtp_hdr->ssrc;
|
||||
state->seq_offset = (state->seq_no + 1) - seq;
|
||||
state->timestamp_offset = state->last_timestamp - timestamp;
|
||||
state->patch = 1;
|
||||
LOGP(DMGCP, LOGL_NOTICE, "The SSRC changed... SSRC: %u offset: %d\n",
|
||||
state->ssrc, state->seq_offset);
|
||||
}
|
||||
|
||||
/* apply the offset and store it back to the packet */
|
||||
if (state->patch) {
|
||||
seq += state->seq_offset;
|
||||
rtp_hdr->sequence = htons(seq);
|
||||
rtp_hdr->ssrc = state->orig_ssrc;
|
||||
|
||||
timestamp += state->timestamp_offset;
|
||||
rtp_hdr->timestamp = htonl(timestamp);
|
||||
}
|
||||
|
||||
/* seq changed, now compare if we have lost something */
|
||||
if (state->seq_no + 1u != seq)
|
||||
state->lost_no = abs(seq - (state->seq_no + 1));
|
||||
state->seq_no = seq;
|
||||
|
||||
state->last_timestamp = timestamp;
|
||||
|
||||
if (payload < 0)
|
||||
return;
|
||||
|
||||
rtp_hdr = (struct rtp_hdr *) data;
|
||||
rtp_hdr->payload_type = payload;
|
||||
}
|
||||
|
||||
|
@ -141,10 +177,8 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
|
|||
}
|
||||
|
||||
/* do not forward aynthing... maybe there is a packet from the bts */
|
||||
if (endp->ci == CI_UNUSED) {
|
||||
LOGP(DMGCP, LOGL_DEBUG, "Unknown message on endpoint: 0x%x\n", ENDPOINT_NUMBER(endp));
|
||||
if (endp->ci == CI_UNUSED)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out where to forward it to. This code assumes that we
|
||||
|
@ -155,7 +189,7 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
|
|||
*/
|
||||
#warning "Slight spec violation. With connection mode recvonly we should attempt to forward."
|
||||
dest = memcmp(&addr.sin_addr, &endp->remote, sizeof(addr.sin_addr)) == 0 &&
|
||||
(endp->net_rtp == addr.sin_port || endp->net_rtcp == addr.sin_port)
|
||||
(endp->net_rtp == addr.sin_port || endp->net_rtcp == addr.sin_port)
|
||||
? DEST_BTS : DEST_NETWORK;
|
||||
proto = fd == &endp->local_rtp ? PROTO_RTP : PROTO_RTCP;
|
||||
|
||||
|
@ -196,15 +230,21 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
|
|||
if (cfg->audio_loop)
|
||||
dest = !dest;
|
||||
|
||||
/* Loop based on the conn_mode, maybe undoing the above */
|
||||
if (endp->conn_mode == MGCP_CONN_LOOPBACK)
|
||||
dest = !dest;
|
||||
|
||||
if (dest == DEST_NETWORK) {
|
||||
if (proto == PROTO_RTP)
|
||||
patch_payload(endp->net_payload_type, buf, rc);
|
||||
patch_and_count(&endp->bts_state,
|
||||
endp->net_payload_type, buf, rc);
|
||||
return udp_send(fd->fd, &endp->remote,
|
||||
proto == PROTO_RTP ? endp->net_rtp : endp->net_rtcp,
|
||||
buf, rc);
|
||||
} else {
|
||||
if (proto == PROTO_RTP)
|
||||
patch_payload(endp->bts_payload_type, buf, rc);
|
||||
patch_and_count(&endp->net_state,
|
||||
endp->bts_payload_type, buf, rc);
|
||||
return udp_send(fd->fd, &endp->bts,
|
||||
proto == PROTO_RTP ? endp->bts_rtp : endp->bts_rtcp,
|
||||
buf, rc);
|
||||
|
|
|
@ -360,6 +360,8 @@ static int parse_conn_mode(const char* msg, int *conn_mode)
|
|||
*conn_mode = MGCP_CONN_RECV_ONLY;
|
||||
else if (strcmp(msg, "sendrecv") == 0)
|
||||
*conn_mode = MGCP_CONN_RECV_SEND;
|
||||
else if (strcmp(msg, "loopback") == 0)
|
||||
*conn_mode = MGCP_CONN_LOOPBACK;
|
||||
else {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Unknown connection mode: '%s'\n", msg);
|
||||
ret = -1;
|
||||
|
@ -385,6 +387,7 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
|
|||
if (cfg->force_realloc) {
|
||||
LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
mgcp_free_endp(endp);
|
||||
} else {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
|
||||
ENDPOINT_NUMBER(endp));
|
||||
|
@ -409,6 +412,8 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
|
|||
error_code = 517;
|
||||
goto error2;
|
||||
}
|
||||
|
||||
endp->orig_mode = endp->conn_mode;
|
||||
break;
|
||||
default:
|
||||
LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
|
||||
|
@ -513,6 +518,7 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg)
|
|||
error_code = 517;
|
||||
goto error3;
|
||||
}
|
||||
endp->orig_mode = endp->conn_mode;
|
||||
break;
|
||||
case 'Z':
|
||||
silent = strcmp("noanswer", (const char *)&msg->l3h[line_start + 3]) == 0;
|
||||
|
@ -737,7 +743,7 @@ int mgcp_endpoints_allocate(struct mgcp_config *cfg)
|
|||
void mgcp_free_endp(struct mgcp_endpoint *endp)
|
||||
{
|
||||
LOGP(DMGCP, LOGL_DEBUG, "Deleting endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp));
|
||||
endp->ci= CI_UNUSED;
|
||||
endp->ci = CI_UNUSED;
|
||||
|
||||
if (endp->callid) {
|
||||
talloc_free(endp->callid);
|
||||
|
@ -759,4 +765,9 @@ void mgcp_free_endp(struct mgcp_endpoint *endp)
|
|||
endp->in_bts = endp->in_remote = 0;
|
||||
memset(&endp->remote, 0, sizeof(endp->remote));
|
||||
memset(&endp->bts, 0, sizeof(endp->bts));
|
||||
|
||||
memset(&endp->net_state, 0, sizeof(endp->net_state));
|
||||
memset(&endp->bts_state, 0, sizeof(endp->bts_state));
|
||||
|
||||
endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE;
|
||||
}
|
||||
|
|
Reference in New Issue