SIP register not using peer's outbound proxy
authorDavid Vossel <dvossel@digium.com>
Fri, 10 Jul 2009 21:42:10 +0000 (21:42 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 10 Jul 2009 21:42:10 +0000 (21:42 +0000)
If callbackextension is defined for a peer it successfully causes
a registration to occur, but the registration ignores the
outboundproxy settings for the peer.  This patch allows the
peer to be passed to obproxy_get() in transmit_register().

(closes issue #14344)
Reported by: Nick_Lewis
Patches:
      callbackextension_peer_trunk.diff uploaded by dvossel (license 671)
Tested by: dvossel

Review: https://reviewboard.asterisk.org/r/294/

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@205985 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index 4dc4e33..715d7c9 100644 (file)
@@ -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(&reg_string, "%s:%s@%s/%s", peer->username, peer->remotesecret ? peer->remotesecret : peer->secret, peer->tohost, callback) < 0) {
+               if (asprintf(&reg_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 */