res_pjsip: Apply outbound proxy to all SIP requests.
authorJoshua Colp <jcolp@digium.com>
Sat, 14 Dec 2013 17:28:21 +0000 (17:28 +0000)
committerJoshua Colp <jcolp@digium.com>
Sat, 14 Dec 2013 17:28:21 +0000 (17:28 +0000)
Objects which are involved in SIP request creation and sending
now allow an outbound proxy to be specified. For cases where
an endpoint is used the outbound proxy specified there will
be applied.

(closes issue ASTERISK-22673)
Reported by: Antti Yrjola

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

Merged revisions 403811 from http://svn.asterisk.org/svn/asterisk/branches/12

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

include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip/location.c
res/res_pjsip/pjsip_options.c

index 18d1aaf..b3701c0 100644 (file)
@@ -146,6 +146,8 @@ struct ast_sip_contact {
        AST_DECLARE_STRING_FIELDS(
                /*! Full URI of the contact */
                AST_STRING_FIELD(uri);
        AST_DECLARE_STRING_FIELDS(
                /*! Full URI of the contact */
                AST_STRING_FIELD(uri);
+               /*! Outbound proxy to use for qualify */
+               AST_STRING_FIELD(outbound_proxy);
        );
        /*! Absolute time that this contact is no longer valid after */
        struct timeval expiration_time;
        );
        /*! Absolute time that this contact is no longer valid after */
        struct timeval expiration_time;
@@ -190,6 +192,8 @@ struct ast_sip_aor {
        AST_DECLARE_STRING_FIELDS(
                /*! Voicemail boxes for this AOR */
                AST_STRING_FIELD(mailboxes);
        AST_DECLARE_STRING_FIELDS(
                /*! Voicemail boxes for this AOR */
                AST_STRING_FIELD(mailboxes);
+               /*! Outbound proxy for OPTIONS requests */
+               AST_STRING_FIELD(outbound_proxy);
        );
        /*! Minimum expiration time */
        unsigned int minimum_expiration;
        );
        /*! Minimum expiration time */
        unsigned int minimum_expiration;
@@ -1278,6 +1282,16 @@ int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pj
 struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata);
 
 /*!
 struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata);
 
 /*!
+ * \brief Set the outbound proxy for an outbound SIP message
+ *
+ * \param tdata The message to set the outbound proxy on
+ * \param proxy SIP uri of the proxy
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy);
+
+/*!
  * \brief Add a header to an outbound SIP message
  *
  * \param tdata The message to add the header to
  * \brief Add a header to an outbound SIP message
  *
  * \param tdata The message to add the header to
index 08c4552..5abb1f3 100644 (file)
                                                If <literal>0</literal> never qualify. Time in seconds.
                                        </para></description>
                                </configOption>
                                                If <literal>0</literal> never qualify. Time in seconds.
                                        </para></description>
                                </configOption>
+                               <configOption name="outbound_proxy">
+                                       <synopsis>Outbound proxy used when sending OPTIONS request</synopsis>
+                                       <description><para>
+                                               If set the provided URI will be used as the outbound proxy when an
+                                               OPTIONS request is sent to a contact for qualify purposes.
+                                       </para></description>
+                               </configOption>
                        </configObject>
                        <configObject name="aor">
                                <synopsis>The configuration for a location of an endpoint</synopsis>
                        </configObject>
                        <configObject name="aor">
                                <synopsis>The configuration for a location of an endpoint</synopsis>
                                                authentication is attempted before declaring the contact available.
                                        </para></description>
                                </configOption>
                                                authentication is attempted before declaring the contact available.
                                        </para></description>
                                </configOption>
+                               <configOption name="outbound_proxy">
+                                       <synopsis>Outbound proxy used when sending OPTIONS request</synopsis>
+                                       <description><para>
+                                               If set the provided URI will be used as the outbound proxy when an
+                                               OPTIONS request is sent to a contact for qualify purposes.
+                                       </para></description>
+                               </configOption>
                        </configObject>
                        <configObject name="system">
                                <synopsis>Options that apply to the SIP stack as well as other system-wide settings</synopsis>
                        </configObject>
                        <configObject name="system">
                                <synopsis>Options that apply to the SIP stack as well as other system-wide settings</synopsis>
@@ -1637,6 +1651,15 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
                return -1;
        }
 
                return -1;
        }
 
+       /* If an outbound proxy is specified on the endpoint apply it to this request */
+       if (endpoint && !ast_strlen_zero(endpoint->outbound_proxy) &&
+               ast_sip_set_outbound_proxy((*tdata), endpoint->outbound_proxy)) {
+               ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s\n",
+                       (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint));
+               pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+               return -1;
+       }
+
        /* We can release this pool since request creation copied all the necessary
         * data into the outbound request's pool
         */
        /* We can release this pool since request creation copied all the necessary
         * data into the outbound request's pool
         */
@@ -1713,6 +1736,22 @@ int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct
        }
 }
 
        }
 }
 
+int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
+{
+       pjsip_route_hdr *route;
+       static const pj_str_t ROUTE_HNAME = { "Route", 5 };
+       pj_str_t tmp;
+
+       pj_strdup2_with_null(tdata->pool, &tmp, proxy);
+       if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
+               return -1;
+       }
+
+       pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route);
+
+       return 0;
+}
+
 int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
 {
        pj_str_t hdr_name;
 int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
 {
        pj_str_t hdr_name;
index 14f5855..ddd8461 100644 (file)
@@ -193,6 +193,10 @@ int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struc
        contact->qualify_frequency = aor->qualify_frequency;
        contact->authenticate_qualify = aor->authenticate_qualify;
 
        contact->qualify_frequency = aor->qualify_frequency;
        contact->authenticate_qualify = aor->authenticate_qualify;
 
+       if (!ast_strlen_zero(aor->outbound_proxy)) {
+               ast_string_field_set(contact, outbound_proxy, aor->outbound_proxy);
+       }
+
        return ast_sorcery_create(ast_sip_get_sorcery(), contact);
 }
 
        return ast_sorcery_create(ast_sip_get_sorcery(), contact);
 }
 
@@ -388,6 +392,7 @@ int ast_sip_initialize_sorcery_location(struct ast_sorcery *sorcery)
        ast_sorcery_object_field_register_custom(sorcery, "contact", "expiration_time", "", expiration_str2struct, expiration_struct2str, 0, 0);
        ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T,
                                          PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400);
        ast_sorcery_object_field_register_custom(sorcery, "contact", "expiration_time", "", expiration_str2struct, expiration_struct2str, 0, 0);
        ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T,
                                          PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400);
+       ast_sorcery_object_field_register(sorcery, "contact", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, outbound_proxy));
 
        ast_sorcery_object_field_register(sorcery, "aor", "type", "", OPT_NOOP_T, 0, 0);
        ast_sorcery_object_field_register(sorcery, "aor", "minimum_expiration", "60", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, minimum_expiration));
 
        ast_sorcery_object_field_register(sorcery, "aor", "type", "", OPT_NOOP_T, 0, 0);
        ast_sorcery_object_field_register(sorcery, "aor", "minimum_expiration", "60", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, minimum_expiration));
@@ -399,6 +404,7 @@ int ast_sip_initialize_sorcery_location(struct ast_sorcery *sorcery)
        ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
        ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, NULL, 0, 0);
        ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes));
        ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
        ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, NULL, 0, 0);
        ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes));
+       ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
 
        ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
        return 0;
 
        ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
        return 0;
index 8d46eb0..0409c15 100644 (file)
@@ -258,6 +258,15 @@ static int qualify_contact(struct ast_sip_contact *contact)
                return -1;
        }
 
                return -1;
        }
 
+       /* If an outbound proxy is specified set it on this request */
+       if (!ast_strlen_zero(contact->outbound_proxy) &&
+               ast_sip_set_outbound_proxy(tdata, contact->outbound_proxy)) {
+               pjsip_tx_data_dec_ref(tdata);
+               ast_log(LOG_ERROR, "Unable to apply outbound proxy on request to qualify contact %s\n",
+                       contact->uri);
+               return -1;
+       }
+
        init_start_time(contact);
 
        ao2_ref(contact, +1);
        init_start_time(contact);
 
        ao2_ref(contact, +1);
@@ -795,6 +804,7 @@ static int qualify_and_schedule_cb(void *obj, void *arg, int flags)
        struct ast_sip_aor *aor = arg;
 
        contact->qualify_frequency = aor->qualify_frequency;
        struct ast_sip_aor *aor = arg;
 
        contact->qualify_frequency = aor->qualify_frequency;
+
        qualify_and_schedule(contact);
 
        return 0;
        qualify_and_schedule(contact);
 
        return 0;