- 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:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user