summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlle Johansson <oej@edvina.net>2006-04-07 08:19:52 +0000
committerOlle Johansson <oej@edvina.net>2006-04-07 08:19:52 +0000
commitb7d32b9e0b29fb216dfe0e01b9df566da35c136c (patch)
treefb5ee1bdbb3228355731a80ff1a317426fd38139
parent255e77ae6e3ee7c9c3fa3f08e188da9860bba5ba (diff)
Issue #6674: Set the URI correctly on BYEs when we have an incoming call
Reported by aubergine, fix by oej git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@18161 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--channels/chan_sip.c103
1 files changed, 65 insertions, 38 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 68c8b94fd..45ed4731b 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -5918,15 +5918,11 @@ static void reg_source_db(struct sip_peer *peer)
register_peer_exten(peer, TRUE);
}
-/*! \brief Parse contact header for 200 OK on INVITE */
+/*! \brief Save contact header for 200 OK on INVITE */
static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
{
char contact[250];
- char *c, *n, *pt;
- int port;
- struct hostent *hp;
- struct ast_hostent ahp;
- struct sockaddr_in oldsin;
+ char *c;
/* Look for brackets */
ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
@@ -5937,28 +5933,54 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
/* Save URI for later ACKs, BYE or RE-invites */
ast_string_field_set(pvt, okcontacturi, c);
-
+
+ /* We should return false for URI:s we can't handle,
+ like sips:, tel:, mailto:,ldap: etc */
+ return TRUE;
+}
+
+/*! \brief Change the other partys IP address based on given contact */
+static int set_address_from_contact(struct sip_pvt *pvt)
+{
+ struct hostent *hp;
+ struct ast_hostent ahp;
+ int port;
+ char *c, *host, *pt;
+ char *contact;
+
+
+ if (ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) {
+ /* NAT: Don't trust the contact field. Just use what they came to us
+ with. */
+ pvt->sa = pvt->recv;
+ return 0;
+ }
+
+
+ /* Work on a copy */
+ contact = ast_strdupa(pvt->fullcontact);
+
/* Make sure it's a SIP URL */
- if (strncasecmp(c, "sip:", 4)) {
- ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", c);
+ if (strncasecmp(contact, "sip:", 4)) {
+ ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact);
} else
- c += 4;
+ contact += 4;
/* Ditch arguments */
- n = strchr(c, ';');
- if (n)
- *n = '\0';
+ host = strchr(contact, ';');
+ if (host)
+ *host = '\0';
/* Grab host */
- n = strchr(c, '@');
- if (!n) {
- n = c;
+ host = strchr(contact, '@');
+ if (!host) { /* No username part */
+ host = contact;
c = NULL;
} else {
- *n = '\0';
- n++;
+ *host = '\0';
+ host++;
}
- pt = strchr(n, ':');
+ pt = strchr(host, ':');
if (pt) {
*pt = '\0';
pt++;
@@ -5966,24 +5988,17 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
} else
port = DEFAULT_SIP_PORT;
- oldsin = pvt->sa;
-
- if (!ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) {
- /* XXX This could block for a long time XXX */
- /* We should only do this if it's a name, not an IP */
- hp = ast_gethostbyname(n, &ahp);
- if (!hp) {
- ast_log(LOG_WARNING, "Invalid host '%s'\n", n);
- return -1;
- }
- pvt->sa.sin_family = AF_INET;
- memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
- pvt->sa.sin_port = htons(port);
- } else {
- /* Don't trust the contact field. Just use what they came to us
- with. */
- pvt->sa = pvt->recv;
+ /* XXX This could block for a long time XXX */
+ /* We should only do this if it's a name, not an IP */
+ hp = ast_gethostbyname(host, &ahp);
+ if (!hp) {
+ ast_log(LOG_WARNING, "Invalid host name in Contact: (can't resolve in DNS) : '%s'\n", host);
+ return -1;
}
+ pvt->sa.sin_family = AF_INET;
+ memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
+ pvt->sa.sin_port = htons(port);
+
return 0;
}
@@ -9746,6 +9761,17 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
/* This is important when we have a SIP proxy between us and the phone */
if (outgoing) {
parse_ok_contact(p, req);
+ if(set_address_from_contact(p)) {
+ /* Bad contact - we don't know how to reach this device */
+ /* We need to ACK, but then send a bye */
+ /* OEJ: Possible issue that may need a check:
+ If we have a proxy route between us and the device,
+ should we care about resolving the contact
+ or should we just send it?
+ */
+ if (!ignore)
+ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ }
/* Save Record-Route for any later requests we make on this dialogue */
build_route(p, req, 1);
@@ -9761,9 +9787,9 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
ast_queue_frame(p->owner, &ast_null_frame);
}
} else {
- /* It's possible we're getting an ACK after we've tried to disconnect
+ /* It's possible we're getting an 200 OK after we've tried to disconnect
by sending CANCEL */
- /* THIS NEEDS TO BE CHECKED: OEJ */
+ /* First send ACK, then send bye */
if (!ignore)
ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
}
@@ -10793,6 +10819,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
copy_request(&p->initreq, req);
if (debug)
ast_verbose("Using INVITE request as basis request - %s\n", p->callid);
+ parse_ok_contact(p, req);
} else { /* Re-invite on existing call */
/* Handle SDP here if we already have an owner */
if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {