|
|
@ -5918,15 +5918,11 @@ static void reg_source_db(struct sip_peer *peer)
|
|
|
|
register_peer_exten(peer, TRUE);
|
|
|
|
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)
|
|
|
|
static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char contact[250];
|
|
|
|
char contact[250];
|
|
|
|
char *c, *n, *pt;
|
|
|
|
char *c;
|
|
|
|
int port;
|
|
|
|
|
|
|
|
struct hostent *hp;
|
|
|
|
|
|
|
|
struct ast_hostent ahp;
|
|
|
|
|
|
|
|
struct sockaddr_in oldsin;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Look for brackets */
|
|
|
|
/* Look for brackets */
|
|
|
|
ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
|
|
|
|
ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
|
|
|
@ -5938,27 +5934,53 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
|
|
|
|
/* Save URI for later ACKs, BYE or RE-invites */
|
|
|
|
/* Save URI for later ACKs, BYE or RE-invites */
|
|
|
|
ast_string_field_set(pvt, okcontacturi, c);
|
|
|
|
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 */
|
|
|
|
/* Make sure it's a SIP URL */
|
|
|
|
if (strncasecmp(c, "sip:", 4)) {
|
|
|
|
if (strncasecmp(contact, "sip:", 4)) {
|
|
|
|
ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", c);
|
|
|
|
ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact);
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
c += 4;
|
|
|
|
contact += 4;
|
|
|
|
|
|
|
|
|
|
|
|
/* Ditch arguments */
|
|
|
|
/* Ditch arguments */
|
|
|
|
n = strchr(c, ';');
|
|
|
|
host = strchr(contact, ';');
|
|
|
|
if (n)
|
|
|
|
if (host)
|
|
|
|
*n = '\0';
|
|
|
|
*host = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
/* Grab host */
|
|
|
|
/* Grab host */
|
|
|
|
n = strchr(c, '@');
|
|
|
|
host = strchr(contact, '@');
|
|
|
|
if (!n) {
|
|
|
|
if (!host) { /* No username part */
|
|
|
|
n = c;
|
|
|
|
host = contact;
|
|
|
|
c = NULL;
|
|
|
|
c = NULL;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
*n = '\0';
|
|
|
|
*host = '\0';
|
|
|
|
n++;
|
|
|
|
host++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pt = strchr(n, ':');
|
|
|
|
pt = strchr(host, ':');
|
|
|
|
if (pt) {
|
|
|
|
if (pt) {
|
|
|
|
*pt = '\0';
|
|
|
|
*pt = '\0';
|
|
|
|
pt++;
|
|
|
|
pt++;
|
|
|
@ -5966,24 +5988,17 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
port = DEFAULT_SIP_PORT;
|
|
|
|
port = DEFAULT_SIP_PORT;
|
|
|
|
|
|
|
|
|
|
|
|
oldsin = pvt->sa;
|
|
|
|
/* XXX This could block for a long time XXX */
|
|
|
|
|
|
|
|
/* We should only do this if it's a name, not an IP */
|
|
|
|
if (!ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) {
|
|
|
|
hp = ast_gethostbyname(host, &ahp);
|
|
|
|
/* XXX This could block for a long time XXX */
|
|
|
|
if (!hp) {
|
|
|
|
/* We should only do this if it's a name, not an IP */
|
|
|
|
ast_log(LOG_WARNING, "Invalid host name in Contact: (can't resolve in DNS) : '%s'\n", host);
|
|
|
|
hp = ast_gethostbyname(n, &ahp);
|
|
|
|
return -1;
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
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 */
|
|
|
|
/* This is important when we have a SIP proxy between us and the phone */
|
|
|
|
if (outgoing) {
|
|
|
|
if (outgoing) {
|
|
|
|
parse_ok_contact(p, req);
|
|
|
|
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 */
|
|
|
|
/* Save Record-Route for any later requests we make on this dialogue */
|
|
|
|
build_route(p, req, 1);
|
|
|
|
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);
|
|
|
|
ast_queue_frame(p->owner, &ast_null_frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} 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 */
|
|
|
|
by sending CANCEL */
|
|
|
|
/* THIS NEEDS TO BE CHECKED: OEJ */
|
|
|
|
/* First send ACK, then send bye */
|
|
|
|
if (!ignore)
|
|
|
|
if (!ignore)
|
|
|
|
ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
|
|
|
|
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);
|
|
|
|
copy_request(&p->initreq, req);
|
|
|
|
if (debug)
|
|
|
|
if (debug)
|
|
|
|
ast_verbose("Using INVITE request as basis request - %s\n", p->callid);
|
|
|
|
ast_verbose("Using INVITE request as basis request - %s\n", p->callid);
|
|
|
|
|
|
|
|
parse_ok_contact(p, req);
|
|
|
|
} else { /* Re-invite on existing call */
|
|
|
|
} else { /* Re-invite on existing call */
|
|
|
|
/* Handle SDP here if we already have an owner */
|
|
|
|
/* Handle SDP here if we already have an owner */
|
|
|
|
if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
|
|
|
|
if (!strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
|
|
|
|