--- channels/chan_sip.c~ 2009-04-20 11:08:26.000000000 -0600 +++ channels/chan_sip.c 2009-05-01 12:57:37.000000000 -0600 @@ -15726,6 +15726,8 @@ static void parse_moved_contact(struct s char *s, *e, *t, *trans; char *domain; enum sip_transport transport = SIP_TRANSPORT_UDP; + char context[256] = "\0"; + const char *forward_context = NULL; ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp)); if ((t = strchr(tmp, ','))) @@ -15759,6 +15761,10 @@ static void parse_moved_contact(struct s p->socket.type = transport; if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { + if (p->owner) { + forward_context = pbx_builtin_getvar_helper(p->owner, "FORWARD_CONTEXT"); + } + char *host = NULL; if (!strncasecmp(s, "sip:", 4)) s += 4; @@ -15770,12 +15776,28 @@ static void parse_moved_contact(struct s if ((host = strchr(s, '@'))) { *host++ = '\0'; ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", s, get_transport(transport), host); - if (p->owner) - ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host); + if (p->owner) { + /* This avoids a hairpin call and the resulting double forward. + * Please note that this requires either a context for the + * domain or FORWARD_CONTEXT to be defined. */ + if (check_sip_domain(host, context, sizeof(context)) && (context[0] || forward_context)) { + ast_string_field_build(p->owner, call_forward, "Local/%s@%s", s, context[0] ? context : forward_context); + } else { + ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host); + } + } } else { ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s); - if (p->owner) - ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s); + if (p->owner) { + /* This avoids a hairpin call and the resulting double forward. + * Please note that this requires either a context for the + * domain or FORWARD_CONTEXT to be defined. */ + if (check_sip_domain(host, context, sizeof(context)) && (context[0] || forward_context)) { + ast_string_field_build(p->owner, call_forward, "Local/%s@%s", s, context[0] ? context : forward_context); + } else { + ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s); + } + } } } else { e = strchr(tmp, '@');