[asterisk-commits] mjordan: trunk r403619 - in /trunk: ./ channels/ channels/pjsip/ channels/pjs...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Dec 11 07:06:32 CST 2013
Author: mjordan
Date: Wed Dec 11 07:06:30 2013
New Revision: 403619
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=403619
Log:
func_channel, chan_pjsip: Add CHANNEL read function support for chan_pjsip
This patch adds CHANNEL read support for chan_pjsip. This allows the dialplan
to use the CHANNEL function on a chan_pjsip channel to obtain run-time
information about the channel from the PJSIP channel driver and the PJSIP
stack. This includes:
* RTP information, including source/destination media addresses, whether or
not the media is secure, held, and other properties.
* RTCP information. This includes sets of parseable information, as well as
individual statistic attriutes.
* PJSIP information. This includes URIs, local/remote signalling addresses,
whether or not the signalling is secure, and other properties.
* The endpoint name. This can be used in conjunction with the PJSIP_ENDPOINT
function to obtain more detailed endpoint information.
Review: https://reviewboard.asterisk.org/r/3038/
........
Merged revisions 403618 from http://svn.asterisk.org/svn/asterisk/branches/12
Added:
trunk/channels/pjsip/
- copied from r403618, branches/12/channels/pjsip/
trunk/channels/pjsip/dialplan_functions.c
- copied unchanged from r403618, branches/12/channels/pjsip/dialplan_functions.c
trunk/channels/pjsip/include/
- copied from r403618, branches/12/channels/pjsip/include/
trunk/channels/pjsip/include/chan_pjsip.h
- copied unchanged from r403618, branches/12/channels/pjsip/include/chan_pjsip.h
trunk/channels/pjsip/include/dialplan_functions.h
- copied unchanged from r403618, branches/12/channels/pjsip/include/dialplan_functions.h
Modified:
trunk/ (props changed)
trunk/channels/Makefile
trunk/channels/chan_pjsip.c
trunk/funcs/func_channel.c
trunk/include/asterisk/res_pjsip_session.h
trunk/main/xmldoc.c
trunk/res/res_pjsip_t38.c
Propchange: trunk/
------------------------------------------------------------------------------
--- branch-12-merged (original)
+++ branch-12-merged Wed Dec 11 07:06:30 2013
@@ -1,1 +1,1 @@
-/branches/12:1-398558,398560-398577,398579-399305,399307-401390,401392-403290,403292-403398,403435,403458,403510,403527,403541-403542,403545,403559,403587,403616
+/branches/12:1-398558,398560-398577,398579-399305,399307-401390,401392-403290,403292-403398,403435,403458,403510,403527,403541-403542,403545,403559,403587,403616,403618
Modified: trunk/channels/Makefile
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/Makefile?view=diff&rev=403619&r1=403618&r2=403619
==============================================================================
--- trunk/channels/Makefile (original)
+++ trunk/channels/Makefile Wed Dec 11 07:06:30 2013
@@ -77,6 +77,9 @@
$(if $(filter chan_sip,$(EMBEDDED_MODS)),modules.link,chan_sip.so): $(subst .c,.o,$(wildcard sip/*.c))
$(subst .c,.o,$(wildcard sip/*.c)): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,chan_sip)
+$(if $(filter chan_pjsip,$(EMBEDDED_MODS)),modules.link,chan_pjsip.so): $(subst .c,.o,$(wildcard pjsip/*.c))
+$(subst .c,.o,$(wildcard pjsip/*.c)): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,chan_pjsip)
+
# Additional objects to combine with chan_dahdi.so
CHAN_DAHDI_OBJS= \
$(subst .c,.o,$(wildcard dahdi/*.c)) \
Modified: trunk/channels/chan_pjsip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_pjsip.c?view=diff&rev=403619&r1=403618&r2=403619
==============================================================================
--- trunk/channels/chan_pjsip.c (original)
+++ trunk/channels/chan_pjsip.c Wed Dec 11 07:06:30 2013
@@ -61,61 +61,13 @@
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
-/*** DOCUMENTATION
- <function name="PJSIP_DIAL_CONTACTS" language="en_US">
- <synopsis>
- Return a dial string for dialing all contacts on an AOR.
- </synopsis>
- <syntax>
- <parameter name="endpoint" required="true">
- <para>Name of the endpoint</para>
- </parameter>
- <parameter name="aor" required="false">
- <para>Name of an AOR to use, if not specified the configured AORs on the endpoint are used</para>
- </parameter>
- <parameter name="request_user" required="false">
- <para>Optional request user to use in the request URI</para>
- </parameter>
- </syntax>
- <description>
- <para>Returns a properly formatted dial string for dialing all contacts on an AOR.</para>
- </description>
- </function>
- <function name="PJSIP_MEDIA_OFFER" language="en_US">
- <synopsis>
- Media and codec offerings to be set on an outbound SIP channel prior to dialing.
- </synopsis>
- <syntax>
- <parameter name="media" required="true">
- <para>types of media offered</para>
- </parameter>
- </syntax>
- <description>
- <para>Returns the codecs offered based upon the media choice</para>
- </description>
- </function>
- ***/
+#include "pjsip/include/chan_pjsip.h"
+#include "pjsip/include/dialplan_functions.h"
static const char desc[] = "PJSIP Channel";
static const char channel_type[] = "PJSIP";
static unsigned int chan_idx;
-
-/*!
- * \brief Positions of various media
- */
-enum sip_session_media_position {
- /*! \brief First is audio */
- SIP_MEDIA_AUDIO = 0,
- /*! \brief Second is video */
- SIP_MEDIA_VIDEO,
- /*! \brief Last is the size for media details */
- SIP_MEDIA_SIZE,
-};
-
-struct chan_pjsip_pvt {
- struct ast_sip_session_media *media[SIP_MEDIA_SIZE];
-};
static void chan_pjsip_pvt_dtor(void *obj)
{
@@ -145,7 +97,7 @@
static int chan_pjsip_queryoption(struct ast_channel *ast, int option, void *data, int *datalen);
/*! \brief PBX interface structure for channel registration */
-static struct ast_channel_tech chan_pjsip_tech = {
+struct ast_channel_tech chan_pjsip_tech = {
.type = channel_type,
.description = "PJSIP Channel Driver",
.requester = chan_pjsip_request,
@@ -164,6 +116,7 @@
.fixup = chan_pjsip_fixup,
.devicestate = chan_pjsip_devicestate,
.queryoption = chan_pjsip_queryoption,
+ .func_channel_read = pjsip_acf_channel_read,
.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER
};
@@ -191,184 +144,6 @@
.incoming_request = chan_pjsip_incoming_ack,
};
-/*! \brief Dialplan function for constructing a dial string for calling all contacts */
-static int chan_pjsip_dial_contacts(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
-{
- RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
- RAII_VAR(struct ast_str *, dial, NULL, ast_free_ptr);
- const char *aor_name;
- char *rest;
-
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(endpoint_name);
- AST_APP_ARG(aor_name);
- AST_APP_ARG(request_user);
- );
-
- AST_STANDARD_APP_ARGS(args, data);
-
- if (ast_strlen_zero(args.endpoint_name)) {
- ast_log(LOG_WARNING, "An endpoint name must be specified when using the '%s' dialplan function\n", cmd);
- return -1;
- } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", args.endpoint_name))) {
- ast_log(LOG_WARNING, "Specified endpoint '%s' was not found\n", args.endpoint_name);
- return -1;
- }
-
- aor_name = S_OR(args.aor_name, endpoint->aors);
-
- if (ast_strlen_zero(aor_name)) {
- ast_log(LOG_WARNING, "No AOR has been provided and no AORs are configured on endpoint '%s'\n", args.endpoint_name);
- return -1;
- } else if (!(dial = ast_str_create(len))) {
- ast_log(LOG_WARNING, "Could not get enough buffer space for dialing contacts\n");
- return -1;
- } else if (!(rest = ast_strdupa(aor_name))) {
- ast_log(LOG_WARNING, "Could not duplicate provided AORs\n");
- return -1;
- }
-
- while ((aor_name = strsep(&rest, ","))) {
- RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
- RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
- struct ao2_iterator it_contacts;
- struct ast_sip_contact *contact;
-
- if (!aor) {
- /* If the AOR provided is not found skip it, there may be more */
- continue;
- } else if (!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
- /* No contacts are available, skip it as well */
- continue;
- } else if (!ao2_container_count(contacts)) {
- /* We were given a container but no contacts are in it... */
- continue;
- }
-
- it_contacts = ao2_iterator_init(contacts, 0);
- for (; (contact = ao2_iterator_next(&it_contacts)); ao2_ref(contact, -1)) {
- ast_str_append(&dial, -1, "PJSIP/");
-
- if (!ast_strlen_zero(args.request_user)) {
- ast_str_append(&dial, -1, "%s@", args.request_user);
- }
- ast_str_append(&dial, -1, "%s/%s&", args.endpoint_name, contact->uri);
- }
- ao2_iterator_destroy(&it_contacts);
- }
-
- /* Trim the '&' at the end off */
- ast_str_truncate(dial, ast_str_strlen(dial) - 1);
-
- ast_copy_string(buf, ast_str_buffer(dial), len);
-
- return 0;
-}
-
-static struct ast_custom_function chan_pjsip_dial_contacts_function = {
- .name = "PJSIP_DIAL_CONTACTS",
- .read = chan_pjsip_dial_contacts,
-};
-
-static int media_offer_read_av(struct ast_sip_session *session, char *buf,
- size_t len, enum ast_format_type media_type)
-{
- int i, size = 0;
- struct ast_format fmt;
- const char *name;
-
- for (i = 0; ast_codec_pref_index(&session->override_prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) != media_type) {
- continue;
- }
-
- name = ast_getformatname(&fmt);
-
- if (ast_strlen_zero(name)) {
- ast_log(LOG_WARNING, "PJSIP_MEDIA_OFFER unrecognized format %s\n", name);
- continue;
- }
-
- /* add one since we'll include a comma */
- size = strlen(name) + 1;
- len -= size;
- if ((len) < 0) {
- break;
- }
-
- /* no reason to use strncat here since we have already ensured buf has
- enough space, so strcat can be safely used */
- strcat(buf, name);
- strcat(buf, ",");
- }
-
- if (size) {
- /* remove the extra comma */
- buf[strlen(buf) - 1] = '\0';
- }
- return 0;
-}
-
-struct media_offer_data {
- struct ast_sip_session *session;
- enum ast_format_type media_type;
- const char *value;
-};
-
-static int media_offer_write_av(void *obj)
-{
- struct media_offer_data *data = obj;
- int i;
- struct ast_format fmt;
- /* remove all of the given media type first */
- for (i = 0; ast_codec_pref_index(&data->session->override_prefs, i, &fmt); ++i) {
- if (AST_FORMAT_GET_TYPE(fmt.id) == data->media_type) {
- ast_codec_pref_remove(&data->session->override_prefs, &fmt);
- }
- }
- ast_format_cap_remove_bytype(data->session->req_caps, data->media_type);
- ast_parse_allow_disallow(&data->session->override_prefs, data->session->req_caps, data->value, 1);
-
- return 0;
-}
-
-static int media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
-{
- struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
-
- if (!strcmp(data, "audio")) {
- return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_AUDIO);
- } else if (!strcmp(data, "video")) {
- return media_offer_read_av(channel->session, buf, len, AST_FORMAT_TYPE_VIDEO);
- }
-
- return 0;
-}
-
-static int media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
-{
- struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
-
- struct media_offer_data mdata = {
- .session = channel->session,
- .value = value
- };
-
- if (!strcmp(data, "audio")) {
- mdata.media_type = AST_FORMAT_TYPE_AUDIO;
- } else if (!strcmp(data, "video")) {
- mdata.media_type = AST_FORMAT_TYPE_VIDEO;
- }
-
- return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata);
-}
-
-static struct ast_custom_function media_offer_function = {
- .name = "PJSIP_MEDIA_OFFER",
- .read = media_offer_read,
- .write = media_offer_write
-};
-
/*! \brief Function called by RTP engine to get local audio RTP peer */
static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
{
@@ -436,6 +211,20 @@
return ast_sip_session_refresh(session, NULL, NULL, NULL,
session->endpoint->media.direct_media.method, 1);
}
+
+/*! \brief Destructor function for \ref transport_info_data */
+static void transport_info_destroy(void *obj)
+{
+ struct transport_info_data *data = obj;
+ ast_free(data);
+}
+
+/*! \brief Datastore used to store local/remote addresses for the
+ * INVITE request that created the PJSIP channel */
+static struct ast_datastore_info transport_info = {
+ .type = "chan_pjsip_transport_info",
+ .destroy = transport_info_destroy,
+};
static struct ast_datastore_info direct_media_mitigation_info = { };
@@ -1989,11 +1778,27 @@
/*! \brief Function called when a request is received on the session */
static int chan_pjsip_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
{
+ RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
+ struct transport_info_data *transport_data;
pjsip_tx_data *packet = NULL;
if (session->channel) {
return 0;
}
+
+ datastore = ast_sip_session_alloc_datastore(&transport_info, "transport_info");
+ if (!datastore) {
+ return -1;
+ }
+
+ transport_data = ast_calloc(1, sizeof(*transport_data));
+ if (!transport_data) {
+ return -1;
+ }
+ pj_sockaddr_cp(&transport_data->local_addr, &rdata->tp_info.transport->local_addr);
+ pj_sockaddr_cp(&transport_data->remote_addr, &rdata->pkt_info.src_addr);
+ datastore->data = transport_data;
+ ast_sip_session_add_datastore(session, datastore);
if (!(session->channel = chan_pjsip_new(session, AST_STATE_RING, session->exten, NULL, NULL, NULL))) {
if (pjsip_inv_end_session(session->inv_session, 503, NULL, &packet) == PJ_SUCCESS) {
@@ -2077,6 +1882,17 @@
}
return 0;
}
+
+static struct ast_custom_function chan_pjsip_dial_contacts_function = {
+ .name = "PJSIP_DIAL_CONTACTS",
+ .read = pjsip_acf_dial_contacts_read,
+};
+
+static struct ast_custom_function media_offer_function = {
+ .name = "PJSIP_MEDIA_OFFER",
+ .read = pjsip_acf_media_offer_read,
+ .write = pjsip_acf_media_offer_write
+};
/*!
* \brief Load the module
@@ -2110,6 +1926,7 @@
if (ast_custom_function_register(&media_offer_function)) {
ast_log(LOG_WARNING, "Unable to register PJSIP_MEDIA_OFFER dialplan function\n");
+ goto end;
}
if (ast_sip_session_register_supplement(&chan_pjsip_supplement)) {
@@ -2150,13 +1967,13 @@
/*! \brief Unload the PJSIP channel from Asterisk */
static int unload_module(void)
{
- ast_custom_function_unregister(&media_offer_function);
-
ast_sip_session_unregister_supplement(&chan_pjsip_supplement);
ast_sip_session_unregister_supplement(&pbx_start_supplement);
ast_sip_session_unregister_supplement(&chan_pjsip_ack_supplement);
+ ast_custom_function_unregister(&media_offer_function);
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
+
ast_channel_unregister(&chan_pjsip_tech);
ast_rtp_glue_unregister(&chan_pjsip_rtp_glue);
Modified: trunk/funcs/func_channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/funcs/func_channel.c?view=diff&rev=403619&r1=403618&r2=403619
==============================================================================
--- trunk/funcs/func_channel.c (original)
+++ trunk/funcs/func_channel.c Wed Dec 11 07:06:30 2013
@@ -280,6 +280,7 @@
<para> Defaults to <literal>audio</literal> if unspecified.</para>
</enum>
</enumlist>
+ <xi:include xpointer="xpointer(/docs/info[@name='PJSIPCHANNEL'])" />
<para><emphasis>chan_iax2</emphasis> provides the following additional options:</para>
<enumlist>
<enum name="osptoken">
Modified: trunk/include/asterisk/res_pjsip_session.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/res_pjsip_session.h?view=diff&rev=403619&r1=403618&r2=403619
==============================================================================
--- trunk/include/asterisk/res_pjsip_session.h (original)
+++ trunk/include/asterisk/res_pjsip_session.h Wed Dec 11 07:06:30 2013
@@ -52,6 +52,7 @@
T38_PEER_REINVITE, /*!< Offered from peer - REINVITE */
T38_ENABLED, /*!< Negotiated (enabled) */
T38_REJECTED, /*!< Refused */
+ T38_MAX_ENUM, /*!< Not an actual state; used as max value in the enum */
};
struct ast_sip_session_sdp_handler;
Modified: trunk/main/xmldoc.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/xmldoc.c?view=diff&rev=403619&r1=403618&r2=403619
==============================================================================
--- trunk/main/xmldoc.c (original)
+++ trunk/main/xmldoc.c Wed Dec 11 07:06:30 2013
@@ -70,6 +70,7 @@
static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *name, int printname);
static int xmldoc_parse_enumlist(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer);
+static void xmldoc_parse_parameter(struct ast_xml_node *fixnode, const char *tabs, struct ast_str **buffer);
static int xmldoc_parse_info(struct ast_xml_node *node, const char *tabs, const char *posttabs, struct ast_str **buffer);
static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const char *posttabs, struct ast_str **buffer);
static int xmldoc_parse_specialtags(struct ast_xml_node *fixnode, const char *tabs, const char *posttabs, struct ast_str **buffer);
@@ -1492,58 +1493,6 @@
/*!
* \internal
- * \brief Parse an 'info' tag inside an element.
- *
- * \param node A pointer to the 'info' xml node.
- * \param tabs A string to be appended at the beginning of each line being printed
- * inside 'buffer'
- * \param posttabs Add this string after the content of the <para> element, if one exists
- * \param String buffer to put values found inide the info element.
- *
- * \retval 2 if the information contained a para element, and it returned a value of 2
- * \retval 1 if information was put into the buffer
- * \retval 0 if no information was put into the buffer or error
- */
-static int xmldoc_parse_info(struct ast_xml_node *node, const char *tabs, const char *posttabs, struct ast_str **buffer)
-{
- const char *tech;
- char *internaltabs;
- int internal_ret;
- int ret = 0;
-
- if (strcasecmp(ast_xml_node_get_name(node), "info")) {
- return ret;
- }
-
- ast_asprintf(&internaltabs, "%s ", tabs);
- if (!internaltabs) {
- return ret;
- }
-
- tech = ast_xml_get_attribute(node, "tech");
- if (tech) {
- ast_str_append(buffer, 0, "%s<note>Technology: %s</note>\n", internaltabs, tech);
- ast_xml_free_attr(tech);
- }
-
- ret = 1;
-
- for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
- if (!strcasecmp(ast_xml_node_get_name(node), "enumlist")) {
- xmldoc_parse_enumlist(node, internaltabs, buffer);
- } else if ((internal_ret = xmldoc_parse_common_elements(node, internaltabs, posttabs, buffer))) {
- if (internal_ret > ret) {
- ret = internal_ret;
- }
- }
- }
- ast_free(internaltabs);
-
- return ret;
-}
-
-/*!
- * \internal
* \brief Parse an <argument> element from the xml documentation.
*
* \param fixnode Pointer to the 'argument' xml node.
@@ -1829,6 +1778,7 @@
}
xmldoc_parse_enumlist(node, optiontabs, buffer);
+ xmldoc_parse_parameter(node, optiontabs, buffer);
}
ast_free(optiontabs);
@@ -2049,6 +1999,60 @@
ast_xml_free_attr(paramname);
}
ast_free(internaltabs);
+}
+
+/*!
+ * \internal
+ * \brief Parse an 'info' tag inside an element.
+ *
+ * \param node A pointer to the 'info' xml node.
+ * \param tabs A string to be appended at the beginning of each line being printed
+ * inside 'buffer'
+ * \param posttabs Add this string after the content of the <para> element, if one exists
+ * \param String buffer to put values found inide the info element.
+ *
+ * \retval 2 if the information contained a para element, and it returned a value of 2
+ * \retval 1 if information was put into the buffer
+ * \retval 0 if no information was put into the buffer or error
+ */
+static int xmldoc_parse_info(struct ast_xml_node *node, const char *tabs, const char *posttabs, struct ast_str **buffer)
+{
+ const char *tech;
+ char *internaltabs;
+ int internal_ret;
+ int ret = 0;
+
+ if (strcasecmp(ast_xml_node_get_name(node), "info")) {
+ return ret;
+ }
+
+ ast_asprintf(&internaltabs, "%s ", tabs);
+ if (!internaltabs) {
+ return ret;
+ }
+
+ tech = ast_xml_get_attribute(node, "tech");
+ if (tech) {
+ ast_str_append(buffer, 0, "%s<note>Technology: %s</note>\n", internaltabs, tech);
+ ast_xml_free_attr(tech);
+ }
+
+ ret = 1;
+
+ for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
+ if (!strcasecmp(ast_xml_node_get_name(node), "enumlist")) {
+ xmldoc_parse_enumlist(node, internaltabs, buffer);
+ } else if (!strcasecmp(ast_xml_node_get_name(node), "parameter")) {
+ xmldoc_parse_parameter(node, internaltabs, buffer);
+ } else if ((internal_ret = xmldoc_parse_common_elements(node, internaltabs, posttabs, buffer))) {
+ if (internal_ret > ret) {
+ ret = internal_ret;
+ }
+ }
+ }
+ ast_free(internaltabs);
+
+ return ret;
}
/*!
Modified: trunk/res/res_pjsip_t38.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip_t38.c?view=diff&rev=403619&r1=403618&r2=403619
==============================================================================
--- trunk/res/res_pjsip_t38.c (original)
+++ trunk/res/res_pjsip_t38.c Wed Dec 11 07:06:30 2013
@@ -171,6 +171,10 @@
break;
case T38_LOCAL_REINVITE:
/* wait until we get a peer response before responding to local reinvite */
+ break;
+ case T38_MAX_ENUM:
+ /* Well, that shouldn't happen */
+ ast_assert(0);
break;
}
More information about the asterisk-commits
mailing list