- improvements on RTP proxy for proxying a "looped" call
(means originating from local UA , via external registrar back to another local UA)
This commit is contained in:
parent
f303dd3b5d
commit
f6b0b49bf9
@ -1,6 +1,9 @@
|
|||||||
0.6.0
|
0.6.0
|
||||||
=====
|
=====
|
||||||
29-May-2007: - Deal with PRACK requests (RFC3262)
|
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
|
25-May-2007: - Just discovered some patches originating from Debian
|
||||||
project - included most of them as they make sense.
|
project - included most of them as they make sense.
|
||||||
(Hint: People, if you get fixes, please drop me a note
|
(Hint: People, if you get fixes, please drop me a note
|
||||||
|
|||||||
52
src/proxy.c
52
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);
|
sts = osip_message_get_body(mymsg, 0, &body);
|
||||||
if (sts != 0) {
|
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: "
|
DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: "
|
||||||
"no body found in message");
|
"no body found in message");
|
||||||
return STS_SUCCESS;
|
return STS_SUCCESS;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sts = sip_body_to_str(body, &buff, &buflen);
|
sts = sip_body_to_str(body, &buff, &buflen);
|
||||||
if (sts != 0) {
|
if (sts != 0) {
|
||||||
ERROR("rewrite_invitation_body: unable to sip_body_to_str");
|
ERROR("rewrite_invitation_body: unable to sip_body_to_str");
|
||||||
|
return STS_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGC(-1, "rewrite_invitation_body: payload %ld bytes", (long)buflen);
|
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)) {
|
if (sdp_message_m_port_get(sdp, media_stream_no)) {
|
||||||
msg_port=atoi(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)) {
|
if ((msg_port > 0) && (msg_port <= 65535)) {
|
||||||
char *client_id=NULL;
|
client_id_t client_id;
|
||||||
static char from_string[HOSTNAME_SIZE];
|
osip_contact_t *contact = NULL;
|
||||||
char *tmp=NULL;
|
char *tmp=NULL;
|
||||||
char *protocol=NULL;
|
char *protocol=NULL;
|
||||||
|
|
||||||
@ -1028,10 +1015,35 @@ if (configuration.debuglevel)
|
|||||||
* particular Header (Contact) or not.
|
* particular Header (Contact) or not.
|
||||||
* I should just go for the remote IP address here, no?
|
* I should just go for the remote IP address here, no?
|
||||||
*/
|
*/
|
||||||
tmp=utils_inet_ntoa(ticket->from.sin_addr);
|
/* &&& NO, using the sender IP will cause troubles if
|
||||||
strncpy(from_string, tmp, HOSTNAME_SIZE);
|
* the remote peer (Proxy/registrar) is thrown out of
|
||||||
from_string[HOSTNAME_SIZE-1]='\0';
|
* the signalling path. Then suddenly the IP address changes.
|
||||||
client_id=from_string;
|
*
|
||||||
|
* 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'
|
* is this an RTP stream ? If yes, set 'isrtp=1'
|
||||||
|
|||||||
@ -72,7 +72,7 @@ int rtpproxy_init( void ) {
|
|||||||
* STS_SUCCESS on success
|
* STS_SUCCESS on success
|
||||||
* STS_FAILURE on error
|
* 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,
|
int direction, int media_stream_no,
|
||||||
struct in_addr local_ipaddr, int *local_port,
|
struct in_addr local_ipaddr, int *local_port,
|
||||||
struct in_addr remote_ipaddr, int remote_port,
|
struct in_addr remote_ipaddr, int remote_port,
|
||||||
|
|||||||
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#define CALLIDNUM_SIZE 256
|
#define CALLIDNUM_SIZE 256
|
||||||
#define CALLIDHOST_SIZE 128
|
#define CALLIDHOST_SIZE 128
|
||||||
#define CLIENT_ID_SIZE 128
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct timeval starttime ;
|
struct timeval starttime ;
|
||||||
@ -42,11 +41,11 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int rtp_rx_sock; /* rx socket (0 -> free slot)*/
|
int rtp_rx_sock; /* rx socket (0 -> free slot)*/
|
||||||
int rtp_tx_sock; /* tx socket */
|
int rtp_tx_sock; /* tx socket */
|
||||||
int rtp_con_rx_sock; /* rx socket rtcp */
|
int rtp_con_rx_sock; /* rx socket rtcp */
|
||||||
int rtp_con_tx_sock; /* tx socket rtcp */
|
int rtp_con_tx_sock; /* tx socket rtcp */
|
||||||
char callid_number[CALLIDNUM_SIZE]; /* call ID */
|
char callid_number[CALLIDNUM_SIZE]; /* call ID */
|
||||||
char callid_host[CALLIDHOST_SIZE]; /* --"-- */
|
char callid_host[CALLIDHOST_SIZE]; /* --"-- */
|
||||||
char client_id[CLIENT_ID_SIZE];
|
client_id_t client_id;
|
||||||
int direction; /* Direction of RTP stream */
|
int direction; /* Direction of RTP stream */
|
||||||
int media_stream_no;
|
int media_stream_no;
|
||||||
timecontrol_t tc;
|
timecontrol_t tc;
|
||||||
@ -62,7 +61,7 @@ typedef struct {
|
|||||||
* RTP relay
|
* RTP relay
|
||||||
*/
|
*/
|
||||||
int rtp_relay_init(void);
|
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,
|
int rtp_direction, int media_stream_no,
|
||||||
struct in_addr local_ipaddr, int *local_port,
|
struct in_addr local_ipaddr, int *local_port,
|
||||||
struct in_addr remote_ipaddr, int remote_port,
|
struct in_addr remote_ipaddr, int remote_port,
|
||||||
|
|||||||
@ -441,7 +441,7 @@ static void *rtpproxy_main(void *arg) {
|
|||||||
* STS_SUCCESS on success
|
* STS_SUCCESS on success
|
||||||
* STS_FAILURE on error
|
* 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 rtp_direction,
|
||||||
int media_stream_no, struct in_addr local_ipaddr,
|
int media_stream_no, struct in_addr local_ipaddr,
|
||||||
int *local_port, struct in_addr remote_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;
|
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
|
* life insurance: check size of received call_id strings
|
||||||
* I don't know what the maximum allowed size within SIP is,
|
* 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);
|
callid->host, (long)strlen(callid->host),CALLIDHOST_SIZE);
|
||||||
return STS_FAILURE;
|
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 "
|
DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: starting RTP proxy "
|
||||||
"stream for: %s@%s[%s] (%s) #=%i",
|
"stream for: CallID=%s@%s [Client-ID=%s] (%s) #=%i",
|
||||||
callid->number, callid->host, client_id,
|
callid->number, callid->host, client_id.contact,
|
||||||
((rtp_direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"),
|
((rtp_direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"),
|
||||||
media_stream_no);
|
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) &&
|
(compare_callid(callid, &cid) == STS_SUCCESS) &&
|
||||||
(rtp_proxytable[i].direction == rtp_direction) &&
|
(rtp_proxytable[i].direction == rtp_direction) &&
|
||||||
(rtp_proxytable[i].media_stream_no == media_stream_no) &&
|
(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
|
* The RTP port number reported by the UA MAY change
|
||||||
* for a given media stream
|
* 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';
|
rtp_proxytable[freeidx].callid_host[0]='\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_id) {
|
/* store the passed Client-ID data */
|
||||||
strcpy(rtp_proxytable[freeidx].client_id, client_id);
|
memcpy(&rtp_proxytable[freeidx].client_id, &client_id, sizeof(client_id_t));
|
||||||
} else {
|
|
||||||
rtp_proxytable[freeidx].client_id[0]='\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
rtp_proxytable[freeidx].direction = rtp_direction;
|
rtp_proxytable[freeidx].direction = rtp_direction;
|
||||||
rtp_proxytable[freeidx].media_stream_no = media_stream_no;
|
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 "
|
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_number,
|
||||||
rtp_proxytable[freeidx].callid_host,
|
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].direction == DIR_INCOMING) ? "incoming RTP" : "outgoing RTP"),
|
||||||
rtp_proxytable[freeidx].media_stream_no, freeidx);
|
rtp_proxytable[freeidx].media_stream_no, freeidx);
|
||||||
|
|
||||||
|
|||||||
@ -117,6 +117,18 @@ typedef struct {
|
|||||||
} sip_ticket_t;
|
} 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
|
* 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);
|
char *utils_inet_ntoa(struct in_addr in);
|
||||||
int utils_inet_aton(const char *cp, struct in_addr *inp);
|
int utils_inet_aton(const char *cp, struct in_addr *inp);
|
||||||
int createpidfile(char *pidfilename); /*X*/
|
int createpidfile(char *pidfilename); /*X*/
|
||||||
|
int compare_client_id(client_id_t cid1, client_id_t cid2); /*X*/
|
||||||
|
|
||||||
/* sip_utils.c */
|
/* sip_utils.c */
|
||||||
osip_message_t * msg_make_template_reply (sip_ticket_t *ticket, int code);
|
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 */
|
/* rtpproxy.c */
|
||||||
int rtpproxy_init( void ); /*X*/
|
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,
|
int direction, int media_stream_no,
|
||||||
struct in_addr outbound_ipaddr, int *outboundport,
|
struct in_addr outbound_ipaddr, int *outboundport,
|
||||||
struct in_addr lcl_client_ipaddr, int lcl_clientport,
|
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) */
|
/* (assume approx one Ethernet MTU) */
|
||||||
|
|
||||||
#define URL_STRING_SIZE 128 /* max size of an URL/URI string */
|
#define URL_STRING_SIZE 128 /* max size of an URL/URI string */
|
||||||
#define STATUSCODE_SIZE 5 /* size of string representation of status */
|
#define STATUSCODE_SIZE 5 /* size of string representation of status */
|
||||||
#define DNS_CACHE_SIZE 256 /* number of entries in internal DNS cache */
|
#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 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_CACHE_SIZE 32 /* number of entries in internal IFADR cache */
|
||||||
#define IFADR_MAX_AGE 5 /* max. age of the IF address cache (sec) */
|
#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 HOSTNAME_SIZE 128 /* max string length of a hostname */
|
||||||
#define USERNAME_SIZE 128 /* max string length of a username (auth) */
|
#define USERNAME_SIZE 128 /* max string length of a username (auth) */
|
||||||
#define PASSWORD_SIZE 128 /* max string length of a password (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() */
|
/* scratch buffer for gethostbyname_r() */
|
||||||
|
|
||||||
#if defined(PR_NETDB_BUF_SIZE)
|
#if defined(PR_NETDB_BUF_SIZE)
|
||||||
#define GETHOSTBYNAME_BUFLEN PR_NETDB_BUF_SIZE
|
#define GETHOSTBYNAME_BUFLEN PR_NETDB_BUF_SIZE
|
||||||
#else
|
#else
|
||||||
|
|||||||
29
src/utils.c
29
src/utils.c
@ -526,3 +526,32 @@ int createpidfile(char *pidfilename) {
|
|||||||
return STS_SUCCESS;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user