diff --git a/ChangeLog b/ChangeLog index c6e7ae1..a466d10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 0.6.0 ===== 29-May-2007: - Deal with PRACK requests (RFC3262) + - improvements on RTP proxy for proxying a "looped" call + (means originating from local UA , via external registrar + back to another local UA) 25-May-2007: - Just discovered some patches originating from Debian project - included most of them as they make sense. (Hint: People, if you get fixes, please drop me a note diff --git a/src/proxy.c b/src/proxy.c index fa07826..d23a46d 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -817,28 +817,15 @@ int proxy_rewrite_invitation_body(sip_ticket_t *ticket, int direction){ */ sts = osip_message_get_body(mymsg, 0, &body); if (sts != 0) { -#if 0 - if ((MSG_IS_RESPONSE_FOR(mymsg,"INVITE")) && - (MSG_IS_STATUS_1XX(mymsg))) { - /* 1xx responses *MAY* contain SDP data */ - DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: " - "no body found in message"); - return STS_SUCCESS; - } else { - /* INVITE request and 200 response *MUST* contain SDP data */ - ERROR("rewrite_invitation_body: no body found in message"); - return STS_FAILURE; - } -#else DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: " "no body found in message"); return STS_SUCCESS; -#endif } sts = sip_body_to_str(body, &buff, &buflen); if (sts != 0) { ERROR("rewrite_invitation_body: unable to sip_body_to_str"); + return STS_FAILURE; } DEBUGC(-1, "rewrite_invitation_body: payload %ld bytes", (long)buflen); @@ -1017,8 +1004,8 @@ if (configuration.debuglevel) if (sdp_message_m_port_get(sdp, media_stream_no)) { msg_port=atoi(sdp_message_m_port_get(sdp, media_stream_no)); if ((msg_port > 0) && (msg_port <= 65535)) { - char *client_id=NULL; - static char from_string[HOSTNAME_SIZE]; + client_id_t client_id; + osip_contact_t *contact = NULL; char *tmp=NULL; char *protocol=NULL; @@ -1028,10 +1015,35 @@ if (configuration.debuglevel) * particular Header (Contact) or not. * I should just go for the remote IP address here, no? */ - tmp=utils_inet_ntoa(ticket->from.sin_addr); - strncpy(from_string, tmp, HOSTNAME_SIZE); - from_string[HOSTNAME_SIZE-1]='\0'; - client_id=from_string; + /* &&& 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 + * + */ + + /* get the Contact Header if present */ + osip_message_get_contact(mymsg, 0, &contact); + osip_contact_to_str(contact, &tmp); + strcpy(client_id.contact, tmp); + + /* 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.c b/src/rtpproxy.c index 73a5f6b..cdb0009 100644 --- a/src/rtpproxy.c +++ b/src/rtpproxy.c @@ -72,7 +72,7 @@ int rtpproxy_init( void ) { * STS_SUCCESS on success * STS_FAILURE on error */ -int rtp_start_fwd (osip_call_id_t *callid, char *client_id, +int rtp_start_fwd (osip_call_id_t *callid, client_id_t client_id, int direction, int media_stream_no, struct in_addr local_ipaddr, int *local_port, struct in_addr remote_ipaddr, int remote_port, diff --git a/src/rtpproxy.h b/src/rtpproxy.h index b56be7c..17f7700 100644 --- a/src/rtpproxy.h +++ b/src/rtpproxy.h @@ -22,7 +22,6 @@ #define CALLIDNUM_SIZE 256 #define CALLIDHOST_SIZE 128 -#define CLIENT_ID_SIZE 128 typedef struct { struct timeval starttime ; @@ -42,11 +41,11 @@ typedef struct { typedef struct { int rtp_rx_sock; /* rx socket (0 -> free slot)*/ int rtp_tx_sock; /* tx socket */ - int rtp_con_rx_sock; /* rx socket rtcp */ - int rtp_con_tx_sock; /* tx socket rtcp */ + int rtp_con_rx_sock; /* rx socket rtcp */ + int rtp_con_tx_sock; /* tx socket rtcp */ char callid_number[CALLIDNUM_SIZE]; /* call ID */ char callid_host[CALLIDHOST_SIZE]; /* --"-- */ - char client_id[CLIENT_ID_SIZE]; + client_id_t client_id; int direction; /* Direction of RTP stream */ int media_stream_no; timecontrol_t tc; @@ -62,7 +61,7 @@ typedef struct { * RTP relay */ int rtp_relay_init(void); -int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, +int rtp_relay_start_fwd (osip_call_id_t *callid, client_id_t client_id, int rtp_direction, int media_stream_no, struct in_addr local_ipaddr, int *local_port, struct in_addr remote_ipaddr, int remote_port, diff --git a/src/rtpproxy_relay.c b/src/rtpproxy_relay.c index fae8196..8621b41 100644 --- a/src/rtpproxy_relay.c +++ b/src/rtpproxy_relay.c @@ -441,7 +441,7 @@ static void *rtpproxy_main(void *arg) { * STS_SUCCESS on success * STS_FAILURE on error */ -int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, +int rtp_relay_start_fwd (osip_call_id_t *callid, client_id_t client_id, int rtp_direction, int media_stream_no, struct in_addr local_ipaddr, int *local_port, struct in_addr remote_ipaddr, @@ -461,11 +461,6 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, return STS_FAILURE; } - if (client_id == NULL) { - ERROR("rtp_relay_start_fwd: did not get a client ID!"); - return STS_FAILURE; - } - /* * life insurance: check size of received call_id strings * I don't know what the maximum allowed size within SIP is, @@ -484,16 +479,10 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, callid->host, (long)strlen(callid->host),CALLIDHOST_SIZE); return STS_FAILURE; } - if (client_id && (strlen(client_id) >= CLIENT_ID_SIZE)) { - ERROR("rtp_relay_start_fwd: client ID [%s] has too many characters " - "(%ld, max=%i)", - client_id, (long)strlen(client_id),CLIENT_ID_SIZE); - return STS_FAILURE; - } DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: starting RTP proxy " - "stream for: %s@%s[%s] (%s) #=%i", - callid->number, callid->host, client_id, + "stream for: CallID=%s@%s [Client-ID=%s] (%s) #=%i", + callid->number, callid->host, client_id.contact, ((rtp_direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"), media_stream_no); @@ -522,7 +511,8 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, (compare_callid(callid, &cid) == STS_SUCCESS) && (rtp_proxytable[i].direction == rtp_direction) && (rtp_proxytable[i].media_stream_no == media_stream_no) && - (strcmp(rtp_proxytable[i].client_id, client_id) == 0)) { + (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 @@ -696,11 +686,8 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, rtp_proxytable[freeidx].callid_host[0]='\0'; } - if (client_id) { - strcpy(rtp_proxytable[freeidx].client_id, client_id); - } else { - rtp_proxytable[freeidx].client_id[0]='\0'; - } + /* store the passed Client-ID data */ + memcpy(&rtp_proxytable[freeidx].client_id, &client_id, sizeof(client_id_t)); rtp_proxytable[freeidx].direction = rtp_direction; rtp_proxytable[freeidx].media_stream_no = media_stream_no; @@ -741,10 +728,10 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, //&&& DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: started RTP proxy " - "stream for: %s@%s[%s] (%s) #=%i idx=%i", + "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, + rtp_proxytable[freeidx].client_id.contact, ((rtp_proxytable[freeidx].direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"), rtp_proxytable[freeidx].media_stream_no, freeidx); diff --git a/src/siproxd.h b/src/siproxd.h index 31ba5a3..76ed866 100644 --- a/src/siproxd.h +++ b/src/siproxd.h @@ -117,6 +117,18 @@ typedef struct { } sip_ticket_t; +/* + * Client_ID - used to identify the two sides of a Call when one + * call is routed twice (in->out and back out->in) through siproxd + * e.g. local UA1 is calling local UA2 via an external Registrar + */ +#define CLIENT_ID_SIZE 128 +typedef struct { + char contact[CLIENT_ID_SIZE]; + struct in_addr from_ip; + /*... maybe more to come ...*/ +} client_id_t; + /* * Function prototypes @@ -164,6 +176,7 @@ int get_interface_ip(int interface, struct in_addr *retaddr); /*X*/ char *utils_inet_ntoa(struct in_addr in); int utils_inet_aton(const char *cp, struct in_addr *inp); int createpidfile(char *pidfilename); /*X*/ +int compare_client_id(client_id_t cid1, client_id_t cid2); /*X*/ /* sip_utils.c */ osip_message_t * msg_make_template_reply (sip_ticket_t *ticket, int code); @@ -189,7 +202,7 @@ int make_default_config(void); /*X*/ /* rtpproxy.c */ int rtpproxy_init( void ); /*X*/ -int rtp_start_fwd (osip_call_id_t *callid, char *client_id, /*X*/ +int rtp_start_fwd (osip_call_id_t *callid, client_id_t client_id, /*X*/ int direction, int media_stream_no, struct in_addr outbound_ipaddr, int *outboundport, struct in_addr lcl_client_ipaddr, int lcl_clientport, @@ -246,8 +259,8 @@ int sip_message_set_body(osip_message_t * sip, const char *buf, size_t len); /* (assume approx one Ethernet MTU) */ #define URL_STRING_SIZE 128 /* max size of an URL/URI string */ -#define STATUSCODE_SIZE 5 /* size of string representation of status */ -#define DNS_CACHE_SIZE 256 /* number of entries in internal DNS cache */ +#define STATUSCODE_SIZE 5 /* size of string representation of status */ +#define DNS_CACHE_SIZE 256 /* number of entries in internal DNS cache */ #define DNS_MAX_AGE 60 /* maximum age of an cache entry (sec) */ #define IFADR_CACHE_SIZE 32 /* number of entries in internal IFADR cache */ #define IFADR_MAX_AGE 5 /* max. age of the IF address cache (sec) */ @@ -255,8 +268,9 @@ int sip_message_set_body(osip_message_t * sip, const char *buf, size_t len); #define HOSTNAME_SIZE 128 /* max string length of a hostname */ #define USERNAME_SIZE 128 /* max string length of a username (auth) */ #define PASSWORD_SIZE 128 /* max string length of a password (auth) */ -#define VIA_BRANCH_SIZE 128 /* max string length for via branch param */ +#define VIA_BRANCH_SIZE 128 /* max string length for via branch param */ /* scratch buffer for gethostbyname_r() */ + #if defined(PR_NETDB_BUF_SIZE) #define GETHOSTBYNAME_BUFLEN PR_NETDB_BUF_SIZE #else diff --git a/src/utils.c b/src/utils.c index 0d82d65..d489718 100644 --- a/src/utils.c +++ b/src/utils.c @@ -526,3 +526,32 @@ int createpidfile(char *pidfilename) { return STS_SUCCESS; } + +/* + * + * + */ +int compare_client_id(client_id_t cid1, client_id_t cid2) { + + /* Prio 1: Contact - if present */ + if ((cid1.contact[0] != '\0') && (cid2.contact[0] != '\0')) { + if (strcmp(cid1.contact, cid2.contact) == 0) { + DEBUGC(DBCLASS_BABBLE, "compare_client_id: contact match [%s]", + cid1.contact); + return STS_SUCCESS; + } + DEBUGC(DBCLASS_BABBLE, "compare_client_id: contact NO match [%s<->%s]", + cid1.contact, cid2.contact); + return STS_FAILURE; + } + + /* Prio 2: IP (always 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)); + return STS_SUCCESS; + } + + DEBUGC(DBCLASS_BABBLE, "compare_client_id: no match"); + return STS_FAILURE; +}