diff --git a/ChangeLog b/ChangeLog index c4c4de2..644381e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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) diff --git a/src/proxy.c b/src/proxy.c index 26d0b7d..ea48cb2 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -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' */ diff --git a/src/rtpproxy_relay.c b/src/rtpproxy_relay.c index 19230b6..a1ca245 100644 --- a/src/rtpproxy_relay.c +++ b/src/rtpproxy_relay.c @@ -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; } } diff --git a/src/siproxd.h b/src/siproxd.h index ebb9b10..8b77910 100644 --- a/src/siproxd.h +++ b/src/siproxd.h @@ -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; diff --git a/src/utils.c b/src/utils.c index feb00f4..ef627f5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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));