make use of received= and rport= fields in sip replies.
In a nutshell, these fields are used to tell a sip entity the address and port its request came from, and are extremely useful in the presence of NATs, especially with symmetric NATs where STUN is totally ineffective. This patch stores the address and port in the 'ourip' field of the dialog descriptor, so they can be reused in subsequent transactions. As it is, it works well for things like REGISTER requiring authentication, because the second REGISTER request (with auth credentials) will carry the correct address. Maybe it can also be useful, in case of an address change, to do one or both of the following: + propagate the new address to the parent user/peer descriptor so that new dialogs will use the correct address from the beginning. This is trivial to implement, I am just waiting for feedback on this. + re-issue a request in case of an address change. This a lot less trivial, maybe unnecessary, and probably covered by the previous item. I would seriously consider this patch for addition to 1.4 and 1.2. The code is very little intrusive, and it would solve in a correct way the nat traversal problems for which externip/externaddr/stunaddr are only a partial and expensive workaround. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@77616 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
2ebdd5fd1d
commit
81bccfe9d9
1 changed files with 41 additions and 0 deletions
|
@ -9701,6 +9701,46 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
|
|||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! \brief check received= and rport= in a SIP response.
|
||||
* If we get a response with received= and/or rport= in the Via:
|
||||
* line, use them as 'p->ourip' (see RFC 3581 for rport,
|
||||
* and RFC 3261 for received).
|
||||
* Using these two fields SIP can produce the correct
|
||||
* address and port in the SIP headers without the need for STUN.
|
||||
* The address part is also reused for the media sessions.
|
||||
* Note that ast_sip_ouraddrfor() still rewrites p->ourip
|
||||
* if you specify externip/seternaddr/stunaddr.
|
||||
*/
|
||||
static void check_via_response(struct sip_pvt *p, struct sip_request *req)
|
||||
{
|
||||
char via[256];
|
||||
char *cur, *opts;
|
||||
|
||||
ast_copy_string(via, get_header(req, "Via"), sizeof(via));
|
||||
|
||||
/* Work on the leftmost value of the topmost Via header */
|
||||
opts = strchr(via, ',');
|
||||
if (opts)
|
||||
*opts = '\0';
|
||||
|
||||
/* parse all relevant options */
|
||||
opts = strchr(via, ';');
|
||||
if (!opts)
|
||||
return; /* no options to parse */
|
||||
*opts++ = '\0';
|
||||
while ( (cur = strsep(&opts, ";")) ) {
|
||||
if (!strncmp(cur, "rport=", 6)) {
|
||||
int port = strtol(cur+6, NULL, 10);
|
||||
/* XXX add error checking */
|
||||
p->ourip.sin_port = ntohs(port);
|
||||
} else if (!strncmp(cur, "received=", 9)) {
|
||||
if (ast_parse_arg(cur+9, PARSE_INADDR, &p->ourip))
|
||||
; /* XXX add error checking */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief check Via: header for hostname, port and rport request/answer */
|
||||
static void check_via(struct sip_pvt *p, struct sip_request *req)
|
||||
{
|
||||
|
@ -13332,6 +13372,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
|
|||
gettag(req, "To", tag, sizeof(tag));
|
||||
ast_string_field_set(p, theirtag, tag);
|
||||
}
|
||||
check_via_response(p, req);
|
||||
if (p->relatedpeer && p->method == SIP_OPTIONS) {
|
||||
/* We don't really care what the response is, just that it replied back.
|
||||
Well, as long as it's not a 100 response... since we might
|
||||
|
|
Reference in a new issue