[asterisk-commits] dlee: branch dlee/stasis-http r380809 - in /team/dlee/stasis-http: include/as...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Feb 4 10:38:00 CST 2013
Author: dlee
Date: Mon Feb 4 10:37:56 2013
New Revision: 380809
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=380809
Log:
Merged kmoore's channel state event caching patch r4
Modified:
team/dlee/stasis-http/include/asterisk/channel.h
team/dlee/stasis-http/include/asterisk/event.h
team/dlee/stasis-http/include/asterisk/event_defs.h
team/dlee/stasis-http/include/asterisk/stringfields.h
team/dlee/stasis-http/main/channel.c
team/dlee/stasis-http/main/event.c
team/dlee/stasis-http/main/manager.c
team/dlee/stasis-http/res/res_security_log.c
team/dlee/stasis-http/tests/test_stringfields.c
Modified: team/dlee/stasis-http/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/channel.h?view=diff&rev=380809&r1=380808&r2=380809
==============================================================================
--- team/dlee/stasis-http/include/asterisk/channel.h (original)
+++ team/dlee/stasis-http/include/asterisk/channel.h Mon Feb 4 10:37:56 2013
@@ -151,6 +151,7 @@
#include "asterisk/channelstate.h"
#include "asterisk/ccss.h"
#include "asterisk/framehook.h"
+#include "asterisk/indications.h"
#define DATASTORE_INHERIT_FOREVER INT_MAX
@@ -4102,4 +4103,83 @@
void ast_channel_dialed_causes_clear(const struct ast_channel *chan);
struct ast_flags *ast_channel_flags(struct ast_channel *chan);
+
+/*!
+ * \since 12
+ * \brief Structure representing a snapshot of channel state.
+ */
+struct ast_channel_snapshot {
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(name); /*!< ASCII unique channel name */
+ AST_STRING_FIELD(accountcode); /*!< Account code for billing */
+ AST_STRING_FIELD(peeraccount); /*!< Peer account code for billing */
+ AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */
+ AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */
+ AST_STRING_FIELD(linkedid); /*!< Linked Channel Identifier -- gets propagated by linkage */
+ AST_STRING_FIELD(parkinglot); /*! Default parking lot, if empty, default parking lot */
+ AST_STRING_FIELD(hangupsource); /*! Who is responsible for hanging up this channel */
+ AST_STRING_FIELD(appl); /*!< Current application */
+ AST_STRING_FIELD(data); /*!< Data passed to current application */
+ AST_STRING_FIELD(context); /*!< Dialplan: Current extension context */
+ AST_STRING_FIELD(exten); /*!< Dialplan: Current extension number */
+ AST_STRING_FIELD(caller_name); /*!< Caller ID Name */
+ AST_STRING_FIELD(caller_number); /*!< Caller ID Number */
+ AST_STRING_FIELD(connected_name); /*!< Connected Line Name */
+ AST_STRING_FIELD(connected_number); /*!< Connected Line Number */
+ );
+
+ struct timeval creationtime; /*!< The time of channel creation */
+ enum ast_channel_state state; /*!< State of line */
+ int priority; /*!< Dialplan: Current extension priority */
+ int amaflags; /*!< AMA flags for billing */
+ int hangupcause; /*!< Why is the channel hanged up. See causes.h */
+ struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */
+};
+
+/*!
+ * \since 12
+ * \brief Generate a snapshot of the channel state
+ *
+ * \param chan The channel from which to generate a snapshot
+ *
+ * \retval pointer on success (must be ast_freed)
+ * \retval NULL on error
+ */
+struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan);
+
+/*!
+ * \since 12
+ * \brief Copy a snapshot of the channel state for use with the event system
+ *
+ * \param copy The snapshot to be copied into
+ * \param orig The snapshot to copy
+ * \param len The length of the snapshots to be copied
+ *
+ * \retval the value passed in via copy on success
+ * \retval NULL on error
+ */
+void *ast_channel_snapshot_copy(void *copy, const void *orig, size_t len);
+
+/*!
+ * \since 12
+ * \brief Compare two channel state snapshots
+ *
+ * \param one The first snapshot to compare
+ * \param one_len The length of the first snapshot to compare
+ * \param two The second snapshot to compare
+ * \param two_len The length of the second snapshot to compare
+ *
+ * \retval zero if equal
+ * \retval non-zero if not equal
+ */
+int ast_channel_snapshot_cmp(const void *one, size_t one_len, const void *two, size_t two_len);
+
+/*!
+ * \since 12
+ * \brief Destroy a snapshot of the channel state
+ *
+ * \param orig The snapshot to destroy
+ * \param orig_len The length of the snapshot to destroy
+ */
+void ast_channel_snapshot_destroy(void *orig, size_t orig_len);
#endif /* _ASTERISK_CHANNEL_H */
Modified: team/dlee/stasis-http/include/asterisk/event.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/event.h?view=diff&rev=380809&r1=380808&r2=380809
==============================================================================
--- team/dlee/stasis-http/include/asterisk/event.h (original)
+++ team/dlee/stasis-http/include/asterisk/event.h Mon Feb 4 10:37:56 2013
@@ -203,6 +203,21 @@
enum ast_event_ie_type ie_type, void *data, size_t raw_datalen);
/*!
+ * \brief Append a raw local parameter to a subscription
+ *
+ * \param sub the dynamic subscription allocated with ast_event_subscribe_new()
+ * \param ie_type the information element type for the parameter
+ * \param data the data that must be present in the event to match this subscription
+ * \param raw_datalen length of data
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ * \since 12
+ */
+int ast_event_sub_append_ie_raw_local(struct ast_event_sub *sub,
+ enum ast_event_ie_type ie_type, void *data, size_t raw_datalen);
+
+/*!
* \brief Append an 'exists' parameter to a subscription
*
* \param sub the dynamic subscription allocated with ast_event_subscribe_new()
@@ -512,6 +527,25 @@
const void *data, size_t data_len);
/*!
+ * \brief Append an information element that has a pointer-containing raw payload
+ * \since 12
+ *
+ * \param event the event that the IE will be appended to
+ * \param ie_type the type of IE to append
+ * \param data A pointer to the pointer-containing raw data for the payload of the IE
+ * \param data_len The amount of data to allocate for the payload
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * The pointer to the event will get updated with the new location for the event
+ * that now contains the appended information element. If the re-allocation of
+ * the memory for this event fails, it will be set to NULL.
+ */
+int ast_event_append_ie_raw_local(struct ast_event **event, enum ast_event_ie_type ie_type,
+ const void *data, size_t data_len);
+
+/*!
* \brief Append the global EID IE
*
* \param event the event to append IE to
@@ -594,6 +628,30 @@
uint16_t ast_event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type);
/*!
+ * \brief Get the value of an information element that has a pointer-containing raw payload
+ * \since 12
+ *
+ * \param event The event to get the IE from
+ * \param ie_type the type of information element to retrieve
+ *
+ * \return This returns the payload of the information element with the given type.
+ * If the information element isn't found, NULL will be returned.
+ */
+const void *ast_event_get_ie_raw_local(const struct ast_event *event, enum ast_event_ie_type ie_type);
+
+/*!
+ * \brief Get the length of the pointer-containing raw payload for a particular IE
+ * \since 12
+ *
+ * \param event The event to get the IE payload length from
+ * \param ie_type the type of information element to get the length of
+ *
+ * \return If an IE of type ie_type is found, its payload length is returned.
+ * Otherwise, 0 is returned.
+ */
+uint16_t ast_event_get_ie_raw_local_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type);
+
+/*!
* \brief Get the string representation of an information element type
*
* \param ie_type the information element type to get the string representation of
@@ -699,6 +757,16 @@
enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator);
/*!
+ * \brief Get the PL type of the current IE in the iterator instance
+ *
+ * \param iterator The iterator instance
+ *
+ * \return the ie PL type associated with the current IE
+ * \return AST_EVENT_IE_PLTYPE_UNKNOWN if the IE type is unknown
+ */
+enum ast_event_ie_pltype ast_event_iterator_get_ie_pltype(struct ast_event_iterator *iterator);
+
+/*!
* \brief Get the value of the current IE in the iterator as an integer payload
*
* \param iterator The iterator instance
@@ -744,11 +812,40 @@
uint16_t ast_event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator);
/*!
+ * \brief Get the value of the current IE in the iterator instance that has a pointer-containing raw payload
+ * \since 12
+ *
+ * \param iterator The iterator instance
+ *
+ * \return This returns the payload of the information element as type raw local.
+ */
+void *ast_event_iterator_get_ie_raw_local(struct ast_event_iterator *iterator);
+
+/*!
+ * \brief Get the length of the pointer-containing raw payload for the current IE for an iterator
+ *
+ * \param iterator The IE iterator
+ *
+ * \return The payload length of the current IE
+ */
+uint16_t ast_event_iterator_get_ie_raw_local_payload_len(struct ast_event_iterator *iterator);
+
+/*!
* \brief Get the minimum length of an ast_event.
*
* \return minimum amount of memory that will be consumed by any ast_event.
*/
size_t ast_event_minimum_length(void);
+
+/*!
+ * \brief Send a channel state-related event.
+ *
+ * \param chan the channel about which to send information
+ *
+ * \return zero on success
+ * \return non-zero on failure
+ */
+int ast_event_queue_channel_state(struct ast_channel *chan);
#if defined(__cplusplus) || defined(c_plusplus)
}
Modified: team/dlee/stasis-http/include/asterisk/event_defs.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/event_defs.h?view=diff&rev=380809&r1=380808&r2=380809
==============================================================================
--- team/dlee/stasis-http/include/asterisk/event_defs.h (original)
+++ team/dlee/stasis-http/include/asterisk/event_defs.h Mon Feb 4 10:37:56 2013
@@ -60,8 +60,10 @@
AST_EVENT_ACL_CHANGE = 0x0b,
/*! Send out a ping for debugging distributed events */
AST_EVENT_PING = 0x0c,
+ /*! A channel state snapshot */
+ AST_EVENT_CHANNEL_STATE = 0x0d,
/*! Number of event types. This should be the last event type + 1 */
- AST_EVENT_TOTAL = 0x0d,
+ AST_EVENT_TOTAL = 0x0e,
};
/*! \brief Event Information Element types */
@@ -304,8 +306,16 @@
* Payload type: UINT
*/
AST_EVENT_IE_CACHABLE = 0x003d,
+
+ /*!
+ * \brief Channel state summary
+ * Used by: AST_EVENT_CHANNEL_STATE
+ * Payload type: RAW
+ */
+ AST_EVENT_IE_CHANNEL_STATE = 0x003e,
+
/*! \brief Must be the last IE value +1 */
- AST_EVENT_IE_TOTAL = 0x003e,
+ AST_EVENT_IE_TOTAL = 0x003f,
};
/*!
@@ -323,6 +333,8 @@
AST_EVENT_IE_PLTYPE_RAW,
/*! Bit flags (unsigned integer, compared using boolean logic) */
AST_EVENT_IE_PLTYPE_BITFLAGS,
+ /*! Raw data, compared with custom function. May contain pointers. */
+ AST_EVENT_IE_PLTYPE_RAW_LOCAL,
};
/*!
Modified: team/dlee/stasis-http/include/asterisk/stringfields.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/stringfields.h?view=diff&rev=380809&r1=380808&r2=380809
==============================================================================
--- team/dlee/stasis-http/include/asterisk/stringfields.h (original)
+++ team/dlee/stasis-http/include/asterisk/stringfields.h Mon Feb 4 10:37:56 2013
@@ -234,6 +234,27 @@
struct ast_string_field_pool *__field_mgr_pool; \
field_list \
struct ast_string_field_mgr __field_mgr
+
+/*!
+ \brief Compare the string fields in two instances of the same structure
+ \param instance1 The first instance of the structure to be compared
+ \param instance2 The second instance of the structure to be compared
+*/
+#define ast_string_field_cmp(instance1, instance2) \
+({ \
+ int cmp = 0; \
+ size_t ptr_size = sizeof(char *); \
+ int len = ((void *)&(instance1)->__field_mgr - (void *)&(instance1)->__field_mgr_pool)/ptr_size - 1; \
+ char **head1 = (void *)&(instance1)->__field_mgr_pool + ptr_size; \
+ char **head2 = (void *)&(instance2)->__field_mgr_pool + ptr_size; \
+ for (; len >= 0; len--) { \
+ cmp = strcmp(head1[len], head2[len]); \
+ if (cmp) { \
+ break; \
+ } \
+ } \
+ cmp; \
+})
/*!
\brief Initialize a field pool and fields
Modified: team/dlee/stasis-http/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/main/channel.c?view=diff&rev=380809&r1=380808&r2=380809
==============================================================================
--- team/dlee/stasis-http/main/channel.c (original)
+++ team/dlee/stasis-http/main/channel.c Mon Feb 4 10:37:56 2013
@@ -1145,34 +1145,7 @@
* a lot of data into this func to do it here!
*/
if (ast_get_channel_tech(tech) || (tech2 && ast_get_channel_tech(tech2))) {
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a new channel is created.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newstate']/managerEventInstance/syntax/parameter[@name='ChannelState'])" />
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newstate']/managerEventInstance/syntax/parameter[@name='ChannelStateDesc'])" />
- </syntax>
- </managerEventInstance>
- ***/
- ast_manager_event(tmp, EVENT_FLAG_CALL, "Newchannel",
- "Channel: %s\r\n"
- "ChannelState: %d\r\n"
- "ChannelStateDesc: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "AccountCode: %s\r\n"
- "Exten: %s\r\n"
- "Context: %s\r\n"
- "Uniqueid: %s\r\n",
- ast_channel_name(tmp),
- state,
- ast_state2str(state),
- S_OR(cid_num, ""),
- S_OR(cid_name, ""),
- ast_channel_accountcode(tmp),
- S_OR(exten, ""),
- S_OR(context, ""),
- ast_channel_uniqueid(tmp));
+ ast_event_queue_channel_state(tmp);
}
ast_channel_internal_finalize(tmp);
@@ -2893,39 +2866,8 @@
ast_channel_unlock(chan);
ast_cc_offer(chan);
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a channel is hung up.</synopsis>
- <syntax>
- <parameter name="Cause">
- <para>A numeric cause code for why the channel was hung up.</para>
- </parameter>
- <parameter name="Cause-txt">
- <para>A description of why the channel was hung up.</para>
- </parameter>
- </syntax>
- </managerEventInstance>
- ***/
- ast_manager_event(chan, EVENT_FLAG_CALL, "Hangup",
- "Channel: %s\r\n"
- "Uniqueid: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "ConnectedLineNum: %s\r\n"
- "ConnectedLineName: %s\r\n"
- "AccountCode: %s\r\n"
- "Cause: %d\r\n"
- "Cause-txt: %s\r\n",
- ast_channel_name(chan),
- ast_channel_uniqueid(chan),
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
- S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>"),
- S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "<unknown>"),
- S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "<unknown>"),
- ast_channel_accountcode(chan),
- ast_channel_hangupcause(chan),
- ast_cause2str(ast_channel_hangupcause(chan))
- );
+
+ ast_event_queue_channel_state(chan);
if (ast_channel_cdr(chan) && !ast_test_flag(ast_channel_cdr(chan), AST_CDR_FLAG_BRIDGED) &&
!ast_test_flag(ast_channel_cdr(chan), AST_CDR_FLAG_POST_DISABLED) &&
@@ -7437,47 +7379,7 @@
* we override what they are saying the state is and things go amuck. */
ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE) ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), name);
- /* setstate used to conditionally report Newchannel; this is no more */
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a channel's state changes.</synopsis>
- <syntax>
- <parameter name="ChannelState">
- <para>A numeric code for the channel's current state, related to ChannelStateDesc</para>
- </parameter>
- <parameter name="ChannelStateDesc">
- <enumlist>
- <enum name="Down"/>
- <enum name="Rsrvd"/>
- <enum name="OffHook"/>
- <enum name="Dialing"/>
- <enum name="Ring"/>
- <enum name="Ringing"/>
- <enum name="Up"/>
- <enum name="Busy"/>
- <enum name="Dialing Offhook"/>
- <enum name="Pre-ring"/>
- <enum name="Unknown"/>
- </enumlist>
- </parameter>
- </syntax>
- </managerEventInstance>
- ***/
- ast_manager_event(chan, EVENT_FLAG_CALL, "Newstate",
- "Channel: %s\r\n"
- "ChannelState: %d\r\n"
- "ChannelStateDesc: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "ConnectedLineNum: %s\r\n"
- "ConnectedLineName: %s\r\n"
- "Uniqueid: %s\r\n",
- ast_channel_name(chan), ast_channel_state(chan), ast_state2str(ast_channel_state(chan)),
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
- S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""),
- S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""),
- S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""),
- ast_channel_uniqueid(chan));
+ ast_event_queue_channel_state(chan);
return 0;
}
@@ -11281,3 +11183,108 @@
{
ao2_unlink(channels, chan);
}
+
+struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
+{
+ struct ast_channel_snapshot *snapshot;
+
+ snapshot = ast_calloc_with_stringfields(1, struct ast_channel_snapshot, 1024);
+ if (!snapshot) {
+ return NULL;
+ }
+
+ // fill out string fields here
+ ast_string_field_set(snapshot, name, ast_channel_name(chan));
+ ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan));
+ ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan));
+ ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan));
+ ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan));
+ ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan));
+ ast_string_field_set(snapshot, parkinglot, ast_channel_parkinglot(chan));
+ ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan));
+ if (ast_channel_appl(chan)) {
+ ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
+ }
+ if (ast_channel_data(chan)) {
+ ast_string_field_set(snapshot, data, ast_channel_data(chan));
+ }
+ ast_string_field_set(snapshot, context, ast_channel_context(chan));
+ ast_string_field_set(snapshot, exten, ast_channel_exten(chan));
+
+ ast_string_field_set(snapshot, caller_name,
+ S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
+ ast_string_field_set(snapshot, caller_number,
+ S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
+
+ ast_string_field_set(snapshot, connected_name,
+ S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
+ ast_string_field_set(snapshot, connected_number,
+ S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
+
+ // copy other information
+ snapshot->creationtime = ast_channel_creationtime(chan);
+ snapshot->state = ast_channel_state(chan);
+ snapshot->priority = ast_channel_priority(chan);
+ snapshot->amaflags = ast_channel_amaflags(chan);
+ snapshot->hangupcause = ast_channel_hangupcause(chan);
+ snapshot->flags = *ast_channel_flags(chan);
+
+ return snapshot;
+}
+
+void *ast_channel_snapshot_copy(void *copy_in, const void *orig_in, size_t len)
+{
+ struct ast_channel_snapshot *copy = copy_in;
+ const struct ast_channel_snapshot *orig = orig_in;
+ if ((ast_string_field_init(copy, 1024))) {
+ return NULL;
+ }
+ ast_string_field_set(copy, name, orig->name);
+ ast_string_field_set(copy, accountcode, orig->accountcode);
+ ast_string_field_set(copy, peeraccount, orig->peeraccount);
+ ast_string_field_set(copy, userfield, orig->userfield);
+ ast_string_field_set(copy, uniqueid, orig->uniqueid);
+ ast_string_field_set(copy, linkedid, orig->linkedid);
+ ast_string_field_set(copy, parkinglot, orig->parkinglot);
+ ast_string_field_set(copy, hangupsource, orig->hangupsource);
+ ast_string_field_set(copy, appl, orig->appl);
+ ast_string_field_set(copy, data, orig->data);
+ ast_string_field_set(copy, context, orig->context);
+ ast_string_field_set(copy, exten, orig->exten);
+ ast_string_field_set(copy, caller_name, orig->caller_name);
+ ast_string_field_set(copy, caller_number, orig->caller_number);
+ ast_string_field_set(copy, connected_name, orig->connected_name);
+ ast_string_field_set(copy, connected_number, orig->connected_number);
+
+ // copy other information
+ copy->creationtime = orig->creationtime;
+ copy->state = orig->state;
+ copy->priority = orig->priority;
+ copy->amaflags = orig->amaflags;
+ copy->hangupcause = orig->hangupcause;
+ copy->flags = orig->flags;
+ return copy_in;
+}
+
+int ast_channel_snapshot_cmp(const void *one_in, size_t one_len, const void *two_in, size_t two_len)
+{
+ /* Compare string fields */
+ const struct ast_channel_snapshot *one = one_in, *two = two_in;
+ int res = ast_string_field_cmp(one, two);
+ size_t non_str_len, offset;
+
+ if (res) {
+ return res;
+ }
+
+ /* Compare the rest of the structure */
+ offset = (const void *)&one->creationtime - (const void *)one;
+ non_str_len = one_len - offset;
+ return memcmp(one + offset, two + offset, non_str_len);
+}
+
+void ast_channel_snapshot_destroy(void *orig_in, size_t orig_len)
+{
+ struct ast_channel_snapshot *orig = orig_in;
+ ast_string_field_free_memory(orig);
+}
Modified: team/dlee/stasis-http/main/event.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/main/event.c?view=diff&rev=380809&r1=380808&r2=380809
==============================================================================
--- team/dlee/stasis-http/main/event.c (original)
+++ team/dlee/stasis-http/main/event.c Mon Feb 4 10:37:56 2013
@@ -43,6 +43,7 @@
#include "asterisk/taskprocessor.h"
#include "asterisk/astobj2.h"
#include "asterisk/cli.h"
+#include "asterisk/channel.h"
static struct ast_taskprocessor *event_dispatcher;
@@ -51,8 +52,7 @@
*
* \note The format of this structure is important. Since these events may
* be sent directly over a network, changing this structure will break
- * compatibility with older versions. However, at this point, this code
- * has not made it into a release, so it is still fair game for change.
+ * compatibility with older versions.
*/
struct ast_event_ie {
enum ast_event_ie_type ie_type:16;
@@ -143,6 +143,7 @@
static int ast_event_hash_devstate(const void *obj, const int flags);
static int ast_event_hash_devstate_change(const void *obj, const int flags);
static int ast_event_hash_presence_state_change(const void *obj, const int flags);
+static int ast_event_hash_channel_state(const void *obj, const int flags);
#ifdef LOW_MEMORY
#define NUM_CACHE_BUCKETS 17
@@ -191,6 +192,10 @@
.hash_fn = ast_event_hash_presence_state_change,
.cache_args = { AST_EVENT_IE_PRESENCE_STATE, },
},
+ [AST_EVENT_CHANNEL_STATE] = {
+ .hash_fn = ast_event_hash_channel_state,
+ .cache_args = { AST_EVENT_IE_CEL_CHANNAME},
+ },
};
@@ -215,6 +220,7 @@
[AST_EVENT_CEL] = "CEL",
[AST_EVENT_SECURITY] = "Security",
[AST_EVENT_NETWORK_CHANGE] = "NetworkChange",
+ [AST_EVENT_CHANNEL_STATE] = "ChannelState",
};
/*!
@@ -222,7 +228,10 @@
*/
static const struct ie_map {
enum ast_event_ie_pltype ie_pltype;
- const char *name;
+ const char *name; /*!< Human-readable name for the IE type */
+ void *(*copy)(void *copy, const void *orig, size_t len); /*!< Copy constructor used for RAW_LOCAL PLTYPEs */
+ int (*cmp)(const void *one, size_t one_len, const void *two, size_t two_len); /*!< Comparator used for RAW_LOCAL PLTYPEs */
+ void (*destroy)(void *orig, size_t orig_len); /*!< Destructor used for RAW_LOCAL PLTYPEs */
} ie_maps[AST_EVENT_IE_TOTAL] = {
[AST_EVENT_IE_NEWMSGS] = { AST_EVENT_IE_PLTYPE_UINT, "NewMessages" },
[AST_EVENT_IE_OLDMSGS] = { AST_EVENT_IE_PLTYPE_UINT, "OldMessages" },
@@ -279,7 +288,8 @@
[AST_EVENT_IE_RECEIVED_HASH] = { AST_EVENT_IE_PLTYPE_STR, "ReceivedHash" },
[AST_EVENT_IE_USING_PASSWORD] = { AST_EVENT_IE_PLTYPE_UINT, "UsingPassword" },
[AST_EVENT_IE_ATTEMPTED_TRANSPORT] = { AST_EVENT_IE_PLTYPE_STR, "AttemptedTransport" },
- [AST_EVENT_IE_CACHABLE] = { AST_EVENT_IE_PLTYPE_UINT, "Cachable" },
+ [AST_EVENT_IE_CACHABLE] = { AST_EVENT_IE_PLTYPE_UINT, "Cachable" },
+ [AST_EVENT_IE_CHANNEL_STATE] = { AST_EVENT_IE_PLTYPE_RAW_LOCAL, "ChannelState", ast_channel_snapshot_copy, ast_channel_snapshot_cmp, ast_channel_snapshot_destroy },
};
const char *ast_event_get_type_name(const struct ast_event *event)
@@ -364,6 +374,10 @@
ast_free((char *) ie_val->payload.str);
break;
case AST_EVENT_IE_PLTYPE_RAW:
+ ast_free(ie_val->payload.raw);
+ break;
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ ie_maps[ie_val->ie_type].destroy(ie_val->payload.raw, ie_val->raw_datalen);
ast_free(ie_val->payload.raw);
break;
case AST_EVENT_IE_PLTYPE_UINT:
@@ -442,6 +456,13 @@
&& !memcmp(sub_ie_val->payload.raw, event_ie_val->payload.raw,
sub_ie_val->raw_datalen));
break;
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ res = (sub_ie_val->raw_datalen == event_ie_val->raw_datalen
+ && !ie_maps[sub_ie_val->ie_type].cmp(sub_ie_val->payload.raw,
+ sub_ie_val->raw_datalen,
+ event_ie_val->payload.raw,
+ event_ie_val->raw_datalen));
+ break;
case AST_EVENT_IE_PLTYPE_EXISTS:
/* Should never get here since check_ie_vals cannot have this type. */
break;
@@ -507,6 +528,20 @@
ie_value->payload.raw = ast_alloca(datalen);
memcpy(ie_value->payload.raw, data, datalen);
+ ie_value->raw_datalen = datalen;
+ insert = 1;
+ break;
+ }
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+
+ ie_value->payload.raw = ast_alloca(datalen);
+ ie_maps[ie_type].copy(
+ ie_value->payload.raw,
+ data,
+ datalen);
ie_value->raw_datalen = datalen;
insert = 1;
break;
@@ -628,6 +663,29 @@
&& !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_payload_len)) ? 1 : 0;
}
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ {
+ const void *buf = event2 ? ast_event_get_ie_raw_local(event2, ie_val->ie_type) : ie_val->payload.raw;
+ uint16_t ie_payload_len = event2 ? ast_event_get_ie_raw_local_payload_len(event2, ie_val->ie_type) : ie_val->raw_datalen;
+ uint16_t event1_payload_len = ast_event_get_ie_raw_local_payload_len(event, ie_val->ie_type);
+ int event_cmp;
+
+ if (!buf) {
+ return 0;
+ }
+ if (ie_payload_len != event1_payload_len) {
+ return 0;
+ }
+ event_cmp = ie_maps[ie_val->ie_type].cmp(buf,
+ ie_payload_len,
+ ast_event_get_ie_raw_local(event, ie_val->ie_type),
+ event1_payload_len);
+ if (event_cmp) {
+ return 0;
+ }
+ return 1;
+ }
+
case AST_EVENT_IE_PLTYPE_EXISTS:
{
return ast_event_get_ie_raw(event, ie_val->ie_type) ? 1 : 0;
@@ -704,6 +762,9 @@
case AST_EVENT_IE_PLTYPE_RAW:
ast_event_append_ie_raw(&event, ie_val->ie_type, ie_val->payload.raw, ie_val->raw_datalen);
break;
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ ast_event_append_ie_raw_local(&event, ie_val->ie_type, ie_val->payload.raw, ie_val->raw_datalen);
+ break;
}
if (!event)
break;
@@ -901,6 +962,38 @@
return 0;
}
+int ast_event_sub_append_ie_raw_local(struct ast_event_sub *sub,
+ enum ast_event_ie_type ie_type, void *data, size_t raw_local_datalen)
+{
+ struct ast_event_ie_val *ie_val;
+
+ if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
+ return -1;
+ }
+
+ if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
+ return -1;
+ }
+
+ ie_val->ie_type = ie_type;
+ ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_RAW_LOCAL;
+ ie_val->raw_datalen = raw_local_datalen;
+
+ if (!(ie_val->payload.raw = ast_malloc(raw_local_datalen))) {
+ ast_free(ie_val);
+ return -1;
+ }
+
+ ie_maps[ie_type].copy(
+ ie_val->payload.raw,
+ data,
+ raw_local_datalen);
+
+ AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
+
+ return 0;
+}
+
int ast_event_sub_activate(struct ast_event_sub *sub)
{
if (ast_event_check_subscriber(AST_EVENT_SUB,
@@ -969,6 +1062,13 @@
void *data = va_arg(ap, void *);
size_t data_len = va_arg(ap, size_t);
ast_event_sub_append_ie_raw(sub, ie_type, data, data_len);
+ break;
+ }
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ {
+ void *data = va_arg(ap, void *);
+ size_t data_len = va_arg(ap, size_t);
+ ast_event_sub_append_ie_raw_local(sub, ie_type, data, data_len);
break;
}
case AST_EVENT_IE_PLTYPE_EXISTS:
@@ -1053,6 +1153,15 @@
return ntohs(iterator->ie->ie_type);
}
+enum ast_event_ie_pltype ast_event_iterator_get_ie_pltype(struct ast_event_iterator *iterator)
+{
+ enum ast_event_ie_type ie_type = ast_event_iterator_get_ie_type(iterator);
+ if (ie_type < AST_EVENT_IE_TOTAL) {
+ return ie_maps[ie_type].ie_pltype;
+ }
+ return AST_EVENT_IE_PLTYPE_UNKNOWN;
+}
+
uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator)
{
return ntohl(get_unaligned_uint32(iterator->ie->ie_payload));
@@ -1080,6 +1189,16 @@
uint16_t ast_event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator)
{
return ntohs(iterator->ie->ie_payload_len);
+}
+
+void *ast_event_iterator_get_ie_raw_local(struct ast_event_iterator *iterator)
+{
+ return ast_event_iterator_get_ie_raw(iterator);
+}
+
+uint16_t ast_event_iterator_get_ie_raw_local_payload_len(struct ast_event_iterator *iterator)
+{
+ return ast_event_iterator_get_ie_raw_payload_len(iterator);
}
enum ast_event_type ast_event_get_type(const struct ast_event *event)
@@ -1149,6 +1268,16 @@
}
return 0;
+}
+
+const void *ast_event_get_ie_raw_local(const struct ast_event *event, enum ast_event_ie_type ie_type)
+{
+ return ast_event_get_ie_raw(event, ie_type);
+}
+
+uint16_t ast_event_get_ie_raw_local_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type)
+{
+ return ast_event_get_ie_raw_payload_len(event, ie_type);
}
int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type,
@@ -1204,6 +1333,33 @@
ie->ie_type = htons(ie_type);
ie->ie_payload_len = htons(data_len);
memcpy(ie->ie_payload, data, data_len);
+
+ (*event)->event_len = htons(event_len + extra_len);
+
+ return 0;
+}
+
+int ast_event_append_ie_raw_local(struct ast_event **event, enum ast_event_ie_type ie_type,
+ const void *data, size_t data_len)
+{
+ struct ast_event_ie *ie;
+ unsigned int extra_len;
+ uint16_t event_len;
+
+ event_len = ntohs((*event)->event_len);
+ extra_len = sizeof(*ie) + data_len;
+
+ if (!(*event = ast_realloc(*event, event_len + extra_len))) {
+ return -1;
+ }
+
+ ie = (struct ast_event_ie *) ( ((char *) *event) + event_len );
+ ie->ie_type = htons(ie_type);
+ ie->ie_payload_len = htons(data_len);
+ ie_maps[ie_type].copy(
+ ie->ie_payload,
+ data,
+ data_len);
(*event)->event_len = htons(event_len + extra_len);
@@ -1259,6 +1415,19 @@
insert = 1;
break;
}
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+ ie_value->payload.raw = ast_alloca(datalen);
+ ie_maps[ie_type].copy(
+ ie_value->payload.raw,
+ data,
+ datalen);
+ ie_value->raw_datalen = datalen;
+ insert = 1;
+ break;
+ }
case AST_EVENT_IE_PLTYPE_UNKNOWN:
case AST_EVENT_IE_PLTYPE_EXISTS:
break;
@@ -1294,6 +1463,10 @@
ast_event_append_ie_raw(&event, ie_val->ie_type,
ie_val->payload.raw, ie_val->raw_datalen);
break;
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ ast_event_append_ie_raw_local(&event, ie_val->ie_type,
+ ie_val->payload.raw, ie_val->raw_datalen);
+ break;
case AST_EVENT_IE_PLTYPE_EXISTS:
case AST_EVENT_IE_PLTYPE_UNKNOWN:
break;
@@ -1322,6 +1495,21 @@
void ast_event_destroy(struct ast_event *event)
{
+ struct ast_event_iterator iterator;
+ int res;
+
+ /* take care of IE types that need the use of destructors */
+ for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
+ if (ast_event_iterator_get_ie_pltype(&iterator) == AST_EVENT_IE_PLTYPE_RAW_LOCAL) {
+ enum ast_event_ie_type ie_type = ast_event_iterator_get_ie_type(&iterator);
+ void *orig = ast_event_iterator_get_ie_raw_local(&iterator);
+ size_t len = ast_event_iterator_get_ie_raw_local_payload_len(&iterator);
+
+ /* run the destructor */
+ ie_maps[ie_type].destroy(orig, len);
+ }
+ }
+
ast_free(event);
}
@@ -1336,6 +1524,8 @@
{
struct ast_event *dup_event;
uint16_t event_len;
+ struct ast_event_iterator iterator;
+ int res;
event_len = ast_event_get_size(event);
@@ -1344,6 +1534,21 @@
}
memcpy(dup_event, event, event_len);
+
+ /* take care of IE types that need the use of copy constructors */
+ for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
+ if (ast_event_iterator_get_ie_pltype(&iterator) == AST_EVENT_IE_PLTYPE_RAW_LOCAL) {
+ enum ast_event_ie_type ie_type = ast_event_iterator_get_ie_type(&iterator);
+ void *orig = ast_event_iterator_get_ie_raw_local(&iterator);
+ size_t len = ast_event_iterator_get_ie_raw_local_payload_len(&iterator);
+ void *copy = (void *)ast_event_get_ie_raw_local(dup_event, ie_type);
+
+ /* clear this out as if it was never touched */
+ memset(copy, 0, len);
+ /* run the copy constructor */
+ ie_maps[ie_type].copy(copy, orig, len);
+ }
+ }
return dup_event;
}
@@ -1398,6 +1603,13 @@
void *data = va_arg(ap, void *);
size_t datalen = va_arg(ap, size_t);
ast_event_append_ie_raw(&cache_arg_event, ie_type, data, datalen);
+ break;
+ }
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+ ast_event_append_ie_raw_local(&cache_arg_event, ie_type, data, datalen);
break;
}
case AST_EVENT_IE_PLTYPE_EXISTS:
@@ -1638,6 +1850,22 @@
/*!
* \internal
+ * \brief Hash function for AST_EVENT_CHANNEL_STATE
+ *
+ * \param[in] obj an ast_event
+ * \param[in] flags unused
+ *
+ * \return hash value
+ */
+static int ast_event_hash_channel_state(const void *obj, const int flags)
+{
+ const struct ast_event *event = obj;
+
+ return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_CEL_CHANNAME));
+}
+
+/*!
+ * \internal
* \brief Compare two events
*
* \param[in] obj the first event, as an ast_event_ref
@@ -1705,6 +1933,17 @@
}
}
+static void dump_raw_local_ie(struct ast_event_iterator *i, struct ast_cli_args *a)
+{
+ enum ast_event_ie_type ie_type;
+ const char *ie_type_name;
+
+ ie_type = ast_event_iterator_get_ie_type(i);
+ ie_type_name = ast_event_get_ie_type_name(ie_type);
+
+ ast_cli(a->fd, "%s\n", ie_type_name);
+}
+
static int event_dump_cli(void *obj, void *arg, int flags)
{
const struct ast_event_ref *event_ref = obj;
@@ -1747,6 +1986,9 @@
break;
case AST_EVENT_IE_PLTYPE_RAW:
dump_raw_ie(&i, a);
+ break;
+ case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
+ dump_raw_local_ie(&i, a);
break;
}
} while (!ast_event_iterator_next(&i));
@@ -1884,3 +2126,28 @@
{
return sizeof(struct ast_event);
}
+
+int ast_event_queue_channel_state(struct ast_channel *chan)
+{
+ struct ast_channel_snapshot *snapshot = ast_channel_snapshot_create(chan);
+ struct ast_event *newchannel_event;
+ if (!snapshot) {
+ return -1;
+ }
+ newchannel_event = ast_event_new(AST_EVENT_CHANNEL_STATE,
+ AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, ast_channel_name(chan),
+ AST_EVENT_IE_CHANNEL_STATE, AST_EVENT_IE_PLTYPE_RAW_LOCAL, snapshot, sizeof(*snapshot),
+ AST_EVENT_IE_END);
+
+ ast_free(snapshot);
+ if (!newchannel_event) {
+ return -1;
+ }
+
+ if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE)) {
+ ast_event_queue(newchannel_event);
+ } else {
+ ast_event_queue_and_cache(newchannel_event);
+ }
+ return 0;
+}
Modified: team/dlee/stasis-http/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/main/manager.c?view=diff&rev=380809&r1=380808&r2=380809
==============================================================================
--- team/dlee/stasis-http/main/manager.c (original)
+++ team/dlee/stasis-http/main/manager.c Mon Feb 4 10:37:56 2013
@@ -1031,6 +1031,8 @@
static int authtimeout;
static int authlimit;
static char *manager_channelvars;
+static struct ast_event_sub *channel_state_sub; /*!< Subscription for channel state changes */
+struct ao2_container *channel_state_cache; /*!< Holds channel state for diffs */
#define DEFAULT_REALM "asterisk"
static char global_realm[MAXHOSTNAMELEN]; /*!< Default realm */
@@ -7343,6 +7345,192 @@
AST_RWLIST_UNLOCK(&channelvars);
}
+static void manager_newchannel(const struct ast_channel_snapshot *snapshot)
+{
+ /*** DOCUMENTATION
+ <managerEventInstance>
+ <synopsis>Raised when a new channel is created.</synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newstate']/managerEventInstance/syntax/parameter[@name='ChannelState'])" />
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newstate']/managerEventInstance/syntax/parameter[@name='ChannelStateDesc'])" />
+ </syntax>
+ </managerEventInstance>
+ ***/
+ manager_event(EVENT_FLAG_CALL, "Newchannel",
+ "Channel: %s\r\n"
+ "ChannelState: %d\r\n"
+ "ChannelStateDesc: %s\r\n"
+ "CallerIDNum: %s\r\n"
+ "CallerIDName: %s\r\n"
+ "AccountCode: %s\r\n"
+ "Exten: %s\r\n"
+ "Context: %s\r\n"
+ "Uniqueid: %s\r\n",
+ snapshot->name,
+ snapshot->state,
+ ast_state2str(snapshot->state),
+ snapshot->caller_number,
+ snapshot->caller_name,
+ snapshot->accountcode,
+ snapshot->exten,
+ snapshot->context,
+ snapshot->uniqueid);
+}
+
+static void manager_newstate(const struct ast_channel_snapshot *snapshot)
+{
+ /*** DOCUMENTATION
+ <managerEventInstance>
+ <synopsis>Raised when a channel's state changes.</synopsis>
+ <syntax>
+ <parameter name="ChannelState">
+ <para>A numeric code for the channel's current state, related to ChannelStateDesc</para>
+ </parameter>
+ <parameter name="ChannelStateDesc">
+ <enumlist>
+ <enum name="Down"/>
+ <enum name="Rsrvd"/>
+ <enum name="OffHook"/>
+ <enum name="Dialing"/>
+ <enum name="Ring"/>
+ <enum name="Ringing"/>
+ <enum name="Up"/>
+ <enum name="Busy"/>
+ <enum name="Dialing Offhook"/>
+ <enum name="Pre-ring"/>
+ <enum name="Unknown"/>
+ </enumlist>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ ***/
+ manager_event(EVENT_FLAG_CALL, "Newstate",
+ "Channel: %s\r\n"
+ "ChannelState: %d\r\n"
+ "ChannelStateDesc: %s\r\n"
+ "CallerIDNum: %s\r\n"
+ "CallerIDName: %s\r\n"
+ "ConnectedLineNum: %s\r\n"
+ "ConnectedLineName: %s\r\n"
+ "Uniqueid: %s\r\n",
+ snapshot->name,
+ snapshot->state,
+ ast_state2str(snapshot->state),
+ snapshot->caller_number,
+ snapshot->caller_name,
+ snapshot->connected_number,
+ snapshot->connected_name,
+ snapshot->uniqueid);
+}
+
+static void manager_hangup(const struct ast_channel_snapshot *snapshot)
+{
+ /*** DOCUMENTATION
+ <managerEventInstance>
+ <synopsis>Raised when a channel is hung up.</synopsis>
[... 280 lines stripped ...]
More information about the asterisk-commits
mailing list