diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 4dc4e33e4d..715d7c9fde 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2077,6 +2077,7 @@ struct sip_registry { AST_STRING_FIELD(md5secret); /*!< Password in md5 */ AST_STRING_FIELD(callback); /*!< Contact extension */ AST_STRING_FIELD(random); + AST_STRING_FIELD(peername); /*!< Peer registering to */ ); enum sip_transport transport; /*!< Transport for this registration UDP, TCP or TLS */ int portno; /*!< Optional port override */ @@ -7444,26 +7445,34 @@ static int sip_register(const char *value, int lineno) enum sip_transport transport = SIP_TRANSPORT_UDP; char buf[256] = ""; char *username = NULL; - char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *buf2=NULL; - char *callback=NULL; + char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *tmp=NULL; + char *callback=NULL, *peername=NULL; if (!value) return -1; - ast_copy_string(buf, value, sizeof(buf)); - buf2 = strrchr(buf, '@'); + tmp = strrchr(buf, '@'); /* split [/extension][~expiry] */ - expire = strchr(buf2, '~'); + expire = strchr(tmp, '~'); if (expire) *expire++ = '\0'; - callback = strrchr(buf2, '/'); + callback = strrchr(tmp, '/'); if (callback) *callback++ = '\0'; if (ast_strlen_zero(callback)) callback = "s"; - sip_parse_host(buf, lineno, &username, &portnum, &transport); + /* split [peername?][transport://] */ + tmp = strchr(buf, '?'); + if (tmp) { + *tmp++ = '\0'; + peername = buf; + } else { + tmp = buf; + } + /* tmp is set at the beginning of [transport://] */ + sip_parse_host(tmp, lineno, &username, &portnum, &transport); /* First split around the last '@' then parse the two components. */ hostname = strrchr(username, '@'); /* allow @ in the first part */ @@ -7513,6 +7522,9 @@ static int sip_register(const char *value, int lineno) ast_string_field_set(reg, authuser, authuser); if (secret) ast_string_field_set(reg, secret, secret); + if (peername) { + ast_string_field_set(reg, peername, peername); + } reg->transport = transport; reg->expire = -1; reg->expiry = (expire ? atoi(expire) : default_expiry); @@ -11549,6 +11561,8 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * } } else { /* Build callid for registration if we haven't registered before */ + struct sip_peer *peer = NULL; + if (!r->callid_valid) { build_callid_registry(r, internip.sin_addr, default_fromdomain); r->callid_valid = TRUE; @@ -11562,8 +11576,15 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * if (p->do_history) append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname); - ref_proxy(p, obproxy_get(p, NULL)); - + if (!ast_strlen_zero(r->peername)) { + if (!(peer = find_peer(r->peername, NULL, 1, FINDPEERS, FALSE))) { + ast_log(LOG_WARNING, "Could not find peer %s in transmit_register\n", r->peername); + } + } + ref_proxy(p, obproxy_get(p, peer)); /* it is ok to pass a NULL peer into obproxy_get() */ + if (peer) { + unref_peer(peer, "transmit_registration: from find_peer operation"); + } /* Use port number specified if no SRV record was found */ if (!r->us.sin_port && r->portno) r->us.sin_port = htons(r->portno); @@ -24495,8 +24516,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str ast_free_ha(oldha); if (!ast_strlen_zero(callback)) { /* build string from peer info */ char *reg_string; - - if (asprintf(®_string, "%s:%s@%s/%s", peer->username, peer->remotesecret ? peer->remotesecret : peer->secret, peer->tohost, callback) < 0) { + if (asprintf(®_string, "%s?%s:%s@%s/%s", peer->name, peer->username, peer->remotesecret ? peer->remotesecret : peer->secret, peer->tohost, callback) < 0) { ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); } else if (reg_string) { sip_register(reg_string, 0); /* XXX TODO: count in registry_count */