- RTP proxy could get confused and mess up RTP streams

if two local UAs did use the same usernames but register
  on different providers. A call from UA1 to UA2 the could
  mess up the audio.
This commit is contained in:
Thomas Ries
2009-07-30 17:02:36 +00:00
parent 6e94ec17d0
commit 4d988c2536
5 changed files with 70 additions and 38 deletions
+4
View File
@@ -1,5 +1,9 @@
0.7.2
=====
30-Jul-2009: - RTP proxy could get confused and mess up RTP streams
if two local UAs did use the same usernames but register
on different providers. A call from UA1 to UA2 the could
mess up the audio.
21-May-2009: - Updated the documentation (plugin related stuff)
24-Mar-2009: - allow the usage of @ in shortdial entries to call
other users on other sip networks (patch by Andreas)
+40 -26
View File
@@ -979,47 +979,61 @@ if (configuration.debuglevel)
if ((msg_port > 0) && (msg_port <= 65535)) {
client_id_t client_id;
osip_contact_t *contact = NULL;
char *tmp=NULL;
char *protocol=NULL;
/* try to get some additional UA specific unique ID.
* This Client-ID should be guaranteed persistent
* and not depend on if a UA/Server does include a
* particular Header (Contact) or not.
* I should just go for the remote IP address here, no?
*/
/* &&& NO, using the sender IP will cause troubles if
* the remote peer (Proxy/registrar) is thrown out of
* the signalling path. Then suddenly the IP address changes.
*
* I should probably go back to the Contact Header based idea,
* with fallback to IP.
* I must use a n-item structure, including all things that
* can be used for comparing. Then, in the RTP proxy, comparison
* must take place according to priorities with the item
* with highest priority present in the RTP table *and*
* extracted from the SIP message.
* To start with, this can be just 2 things, the Contact header
* and the Layer 3 IP address. As long as the UAs include the
* Contact header, we survive IP changes (e.g. when the SIP
* Registrar/Proxy is removed from signalling path within an
* ongoing call. This may happen if the Registrar/Proxy does
* not explicitely ask to stay in the signalling path using
* Record-Route headers - which is perfectly legal
*
*/
/* we will use - if present the from/to fields.
* Outgoing call (RQ out, RS in => use the "from" field to identify local client
* Incoming call (RQ in, RS out => use the "to" field to identify local client
*/
/* If no proper TO/FROM headers are present, fall back to use Contact header... */
memset(&client_id, 0, sizeof(client_id));
/* get the Contact Header if present */
osip_message_get_contact(mymsg, 0, &contact);
if (contact) osip_contact_to_str(contact, &tmp);
if (tmp) strncpy(client_id.contact, tmp, CLIENT_ID_SIZE-1);
/* Outgoing call (RQ out, RS in => use the "from" field to identify local client */
if ((MSG_IS_REQUEST(mymsg) && direction == DIR_OUTGOING) ||
(!MSG_IS_REQUEST(mymsg) && direction == DIR_INCOMING)) {
/* I have a full FROM SIP URI 'user@host' */
if (mymsg->from && mymsg->from->url &&
mymsg->from->url->username && mymsg->from->url->host) {
snprintf(client_id.idstring, CLIENT_ID_SIZE-1, "%s@%s",
mymsg->from->url->username, mymsg->from->url->host);
} else {
char *tmp=NULL;
/* get the Contact Header if present */
osip_message_get_contact(mymsg, 0, &contact);
if (contact) osip_contact_to_str(contact, &tmp);
if (tmp) strncpy(client_id.idstring, tmp, CLIENT_ID_SIZE-1);
} /* if from header */
/* Incoming call (RQ in, RS out => use the "to" field to identify local client */
} else { /*(MSG_IS_REQUEST(mymsg) && direction == DIR_INCOMING) ||
(!MSG_IS_REQUEST(mymsg) && direction == DIR_OUTGOING)) */
/* I have a full TO SIP URI 'user@host' */
if (mymsg->to && mymsg->to->url &&
mymsg->to->url->username && mymsg->to->url->host) {
snprintf(client_id.idstring, CLIENT_ID_SIZE-1, "%s@%s",
mymsg->to->url->username, mymsg->to->url->host);
} else {
char *tmp=NULL;
/* get the Contact Header if present */
osip_message_get_contact(mymsg, 0, &contact);
if (contact) osip_contact_to_str(contact, &tmp);
if (tmp) strncpy(client_id.idstring, tmp, CLIENT_ID_SIZE-1);
} /* if to header */
}
/* store the IP address of the sender */
memcpy(&client_id.from_ip, &ticket->from.sin_addr,
sizeof(client_id.from_ip));
/*
* is this an RTP stream ? If yes, set 'isrtp=1'
*/
+20 -6
View File
@@ -527,7 +527,7 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, client_id_t client_id,
DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: starting RTP proxy "
"stream for: CallID=%s@%s [Client-ID=%s] (%s) #=%i",
callid->number, callid->host, client_id.contact,
callid->number, callid->host, client_id.idstring,
((rtp_direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"),
media_stream_no);
@@ -556,8 +556,7 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, client_id_t client_id,
(compare_callid(callid, &cid) == STS_SUCCESS) &&
(rtp_proxytable[i].direction == rtp_direction) &&
(rtp_proxytable[i].media_stream_no == media_stream_no) &&
(compare_client_id(rtp_proxytable[i].client_id, client_id) ==
STS_SUCCESS)) {
(compare_client_id(rtp_proxytable[i].client_id, client_id) == STS_SUCCESS)) {
/*
* The RTP port number reported by the UA MAY change
* for a given media stream
@@ -782,7 +781,7 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, client_id_t client_id,
"stream for: CallID=%s@%s [Client-ID=%s] %s #=%i idx=%i",
rtp_proxytable[freeidx].callid_number,
rtp_proxytable[freeidx].callid_host,
rtp_proxytable[freeidx].client_id.contact,
rtp_proxytable[freeidx].client_id.idstring,
((rtp_proxytable[freeidx].direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"),
rtp_proxytable[freeidx].media_stream_no, freeidx);
@@ -1033,12 +1032,27 @@ static void match_socket (int rtp_proxytable_idx) {
(media_stream_no == rtp_proxytable[j].media_stream_no) &&
(rtp_direction != rtp_proxytable[j].direction) /* channel: &&
(channel == rtp_proxytable[j].channel)*/ ) {
char remip1[16], remip2[16];
char lclip1[16], lclip2[16];
/* connect the two sockets */
rtp_proxytable[rtp_proxytable_idx].rtp_tx_sock = rtp_proxytable[j].rtp_rx_sock;
rtp_proxytable[rtp_proxytable_idx].rtp_con_tx_sock = rtp_proxytable[j].rtp_con_rx_sock;
DEBUGC(DBCLASS_RTP, "connected entry %i (fd=%i) <-> entry %i (fd=%i)",
strcpy(remip1, utils_inet_ntoa(rtp_proxytable[j].remote_ipaddr));
strcpy(lclip1, utils_inet_ntoa(rtp_proxytable[j].local_ipaddr));
strcpy(remip2, utils_inet_ntoa(rtp_proxytable[rtp_proxytable_idx].remote_ipaddr));
strcpy(lclip2, utils_inet_ntoa(rtp_proxytable[rtp_proxytable_idx].local_ipaddr));
DEBUGC(DBCLASS_RTP, "connected entry %i (fd=%i, %s:%i->%s:%i) <-> entry %i (fd=%i, %s:%i->%s:%i)",
j, rtp_proxytable[j].rtp_rx_sock,
lclip1, rtp_proxytable[j].local_port,
remip1, rtp_proxytable[j].remote_port,
rtp_proxytable_idx,
rtp_proxytable[rtp_proxytable_idx].rtp_rx_sock);
rtp_proxytable[rtp_proxytable_idx].rtp_rx_sock,
lclip2, rtp_proxytable[rtp_proxytable_idx].local_port,
remip2, rtp_proxytable[rtp_proxytable_idx].remote_port
);
break;
}
}
+1 -1
View File
@@ -137,7 +137,7 @@ typedef struct {
*/
#define CLIENT_ID_SIZE 128
typedef struct {
char contact[CLIENT_ID_SIZE];
char idstring[CLIENT_ID_SIZE];
struct in_addr from_ip;
/*... maybe more to come ...*/
} client_id_t;
+5 -5
View File
@@ -607,18 +607,18 @@ int createpidfile(char *pidfilename) {
int compare_client_id(client_id_t cid1, client_id_t cid2) {
/* Prio 1: Contact - if present in both structures */
if ((cid1.contact[0] != '\0') && (cid2.contact[0] != '\0')) {
if (strncmp(cid1.contact, cid2.contact, CLIENT_ID_SIZE) == 0) {
if ((cid1.idstring[0] != '\0') && (cid2.idstring[0] != '\0')) {
if (strncmp(cid1.idstring, cid2.idstring, CLIENT_ID_SIZE) == 0) {
DEBUGC(DBCLASS_BABBLE, "compare_client_id: contact match [%s]",
cid1.contact);
cid1.idstring);
return STS_SUCCESS;
}
DEBUGC(DBCLASS_BABBLE, "compare_client_id: contact NO match [%s<->%s]",
cid1.contact, cid2.contact);
cid1.idstring, cid2.idstring);
return STS_FAILURE;
}
/* Prio 2: IP (always present) */
/* Prio 2: IP (always present) - fallback, if no ID string present. */
if (memcmp(&cid1.from_ip, &cid2.from_ip, sizeof(struct in_addr)) == 0) {
DEBUGC(DBCLASS_BABBLE, "compare_client_id: IP match [%s]",
utils_inet_ntoa(cid1.from_ip));