[asterisk-commits] kmoore: branch kmoore/channel-state-caching r380842 - in /team/kmoore/channel...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Feb 4 22:12:15 CST 2013


Author: kmoore
Date: Mon Feb  4 22:12:12 2013
New Revision: 380842

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=380842
Log:
Convert to using string fields for channel snapshots

Change channel snapshots over to string fields and create copy,
comparison, and destructor functions for them (and using those
everywhere).

The event system now has support for handling blobs that contain
pointers and need use of these types of functions. This includes the
addition of the new PLTYPE RAW_LOCAL which stores the copy, cmp, and
destroy functions in the ie_maps array and usage of those functions in
event duplication and destruction functions.

Fix segfaults in the manager cache hashing and comparison functions
when OBJ_KEY is used.

Fix bugs in manager event generation from channel state updates.

Modified:
    team/kmoore/channel-state-caching/include/asterisk/channel.h
    team/kmoore/channel-state-caching/include/asterisk/event.h
    team/kmoore/channel-state-caching/include/asterisk/event_defs.h
    team/kmoore/channel-state-caching/main/channel.c
    team/kmoore/channel-state-caching/main/event.c
    team/kmoore/channel-state-caching/main/manager.c
    team/kmoore/channel-state-caching/res/res_security_log.c

Modified: team/kmoore/channel-state-caching/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/channel-state-caching/include/asterisk/channel.h?view=diff&rev=380842&r1=380841&r2=380842
==============================================================================
--- team/kmoore/channel-state-caching/include/asterisk/channel.h (original)
+++ team/kmoore/channel-state-caching/include/asterisk/channel.h Mon Feb  4 22:12:12 2013
@@ -4115,34 +4115,24 @@
  * \brief Structure representing a snapshot of channel state.
  */
 struct ast_channel_snapshot {
-	char name[AST_CHANNEL_NAME];		/*!< ASCII unique channel name */
-	char accountcode[AST_MAX_ACCOUNT_CODE];	/*!< Account code for billing */
-	char peeraccount[AST_MAX_ACCOUNT_CODE];	/*!< Peer account code for billing */
-	char userfield[AST_MAX_USER_FIELD];	/*!< Userfield for CEL billing */
-	char uniqueid[AST_MAX_ID];		/*!< Unique Channel Identifier */
-	char linkedid[AST_MAX_ID];		/*!< Linked Channel Identifier -- gets propagated by linkage */
-	char parkinglot[AST_MAX_GENERIC];	/*! Default parking lot, if empty, default parking lot  */
-	char hangupsource[AST_MAX_GENERIC];	/*! Who is responsible for hanging up this channel */
-	char appl[AST_MAX_APP];			/*!< Current application */
-	char data[AST_MAX_GENERIC];		/*!< Data passed to current application */
-	char context[AST_MAX_CONTEXT];		/*!< Dialplan: Current extension context */
-	char exten[AST_MAX_EXTENSION];		/*!< Dialplan: Current extension number */
-
-	/*!
-	 * \brief Channel Caller ID information.
-	 * \note The caller id information is the caller id of this
-	 * channel when it is used to initiate a call.
-	 */
-	char caller_name[AST_MAX_PARTY];
-	char caller_number[AST_MAX_PARTY];
-
-	/*!
-	 * \brief Channel Connected Line ID information.
-	 * \note The connected line information identifies the channel
-	 * connected/bridged to this channel.
-	 */
-	char connected_name[AST_MAX_PARTY];
-	char connected_number[AST_MAX_PARTY];
+	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 */
@@ -4162,4 +4152,39 @@
  * \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
+ *
+ * \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 result of the comparison
+ */
+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/kmoore/channel-state-caching/include/asterisk/event.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/channel-state-caching/include/asterisk/event.h?view=diff&rev=380842&r1=380841&r2=380842
==============================================================================
--- team/kmoore/channel-state-caching/include/asterisk/event.h (original)
+++ team/kmoore/channel-state-caching/include/asterisk/event.h Mon Feb  4 22:12:12 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
@@ -742,6 +810,25 @@
  * \return The payload length of the current IE
  */
 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.

Modified: team/kmoore/channel-state-caching/include/asterisk/event_defs.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/channel-state-caching/include/asterisk/event_defs.h?view=diff&rev=380842&r1=380841&r2=380842
==============================================================================
--- team/kmoore/channel-state-caching/include/asterisk/event_defs.h (original)
+++ team/kmoore/channel-state-caching/include/asterisk/event_defs.h Mon Feb  4 22:12:12 2013
@@ -333,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/kmoore/channel-state-caching/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/channel-state-caching/main/channel.c?view=diff&rev=380842&r1=380841&r2=380842
==============================================================================
--- team/kmoore/channel-state-caching/main/channel.c (original)
+++ team/kmoore/channel-state-caching/main/channel.c Mon Feb  4 22:12:12 2013
@@ -11188,42 +11188,38 @@
 {
 	struct ast_channel_snapshot *snapshot;
 
-	snapshot = ast_calloc(1, sizeof(*snapshot));
+	snapshot = ast_calloc_with_stringfields(1, struct ast_channel_snapshot, 1024);
 	if (!snapshot) {
 		return NULL;
 	}
 
 	// fill out string fields here
-	ast_copy_string(snapshot->name, ast_channel_name(chan), sizeof(snapshot->name));
-	ast_copy_string(snapshot->accountcode, ast_channel_accountcode(chan), sizeof(snapshot->accountcode));
-	ast_copy_string(snapshot->peeraccount, ast_channel_peeraccount(chan), sizeof(snapshot->peeraccount));
-	ast_copy_string(snapshot->userfield, ast_channel_userfield(chan), sizeof(snapshot->userfield));
-	ast_copy_string(snapshot->uniqueid, ast_channel_uniqueid(chan), sizeof(snapshot->uniqueid));
-	ast_copy_string(snapshot->linkedid, ast_channel_linkedid(chan), sizeof(snapshot->linkedid));
-	ast_copy_string(snapshot->parkinglot, ast_channel_parkinglot(chan), sizeof(snapshot->parkinglot));
-	ast_copy_string(snapshot->hangupsource, ast_channel_hangupsource(chan), sizeof(snapshot->hangupsource));
+	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_copy_string(snapshot->appl, ast_channel_appl(chan), sizeof(snapshot->appl));
+		ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
 	}
 	if (ast_channel_data(chan)) {
-		ast_copy_string(snapshot->data, ast_channel_data(chan), sizeof(snapshot->data));
-	}
-	ast_copy_string(snapshot->context, ast_channel_context(chan), sizeof(snapshot->context));
-	ast_copy_string(snapshot->exten, ast_channel_exten(chan), sizeof(snapshot->exten));
-
-	ast_copy_string(snapshot->caller_name,
-		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""),
-		sizeof(snapshot->caller_name));
-	ast_copy_string(snapshot->caller_number,
-		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
-		sizeof(snapshot->caller_number));
-
-	ast_copy_string(snapshot->connected_name,
-		S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""),
-		sizeof(snapshot->connected_name));
-	ast_copy_string(snapshot->connected_number,
-		S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""),
-		sizeof(snapshot->connected_number));
+		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);
@@ -11235,3 +11231,45 @@
 
 	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_fields_copy(copy, orig);
+
+	// 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_fields_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/kmoore/channel-state-caching/main/event.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/channel-state-caching/main/event.c?view=diff&rev=380842&r1=380841&r2=380842
==============================================================================
--- team/kmoore/channel-state-caching/main/event.c (original)
+++ team/kmoore/channel-state-caching/main/event.c Mon Feb  4 22:12:12 2013
@@ -52,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;
@@ -229,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" },
@@ -287,7 +289,7 @@
 	[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_CHANNEL_STATE]       = { AST_EVENT_IE_PLTYPE_RAW,  "ChannelState" },
+	[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)
@@ -372,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:
@@ -450,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;
@@ -515,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;
@@ -636,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;
@@ -712,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;
@@ -909,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,
@@ -977,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:
@@ -1061,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));
@@ -1088,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)
@@ -1157,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,
@@ -1212,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);
 
@@ -1267,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;
@@ -1302,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;
@@ -1330,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);
 }
 
@@ -1344,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);
 
@@ -1352,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;
 }
@@ -1406,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:
@@ -1729,6 +1933,21 @@
 	}
 }
 
+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);
+
+	switch (ie_type) {
+	default:
+		ast_cli(a->fd, "%s\n", ie_type_name);
+		break;
+	}
+}
+
 static int event_dump_cli(void *obj, void *arg, int flags)
 {
 	const struct ast_event_ref *event_ref = obj;
@@ -1771,6 +1990,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));
@@ -1918,7 +2140,7 @@
 	}
 	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, snapshot, sizeof(*snapshot),
+		AST_EVENT_IE_CHANNEL_STATE,         AST_EVENT_IE_PLTYPE_RAW_LOCAL, snapshot, sizeof(*snapshot),
 		AST_EVENT_IE_END);
 
 	ast_free(snapshot);

Modified: team/kmoore/channel-state-caching/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/channel-state-caching/main/manager.c?view=diff&rev=380842&r1=380841&r2=380842
==============================================================================
--- team/kmoore/channel-state-caching/main/manager.c (original)
+++ team/kmoore/channel-state-caching/main/manager.c Mon Feb  4 22:12:12 2013
@@ -7462,13 +7462,20 @@
 static int channel_state_hash_fn(const void *obj, const int flags)
 {
         const struct ast_channel_snapshot *data = obj;
-        return ast_str_case_hash(data->name);
+	const char *name = (flags & OBJ_KEY) ? obj : data->name;
+        return ast_str_case_hash(name);
 }
 
 static int channel_state_cmp_fn(void *obj, void *arg, int flags)
 {
         const struct ast_channel_snapshot *one = obj, *two = arg;
-        return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP : 0;
+	const char *name = (flags & OBJ_KEY) ? arg : two->name;
+        return !strcasecmp(one->name, name) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+static void channel_snapshot_destroy(void *obj)
+{
+	ast_channel_snapshot_destroy(obj, sizeof(struct ast_channel_snapshot));
 }
 
 static void channel_state_cb(const struct ast_event *event, void *userdata)
@@ -7476,43 +7483,48 @@
 	const struct ast_channel_snapshot *new_snapshot = ast_event_get_ie_raw(event, AST_EVENT_IE_CHANNEL_STATE);
 	struct ast_channel_snapshot *old_snapshot = NULL, *ao2_snapshot = NULL;
 	int is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
-
-	/* Only allocate for a new AO2 object if the channel is not hanging up */
+	int find_flags = OBJ_KEY;
+
+	/* Only allocate for a new AO2 object if the channel is not hung up */
 	if (!is_hungup) {
-		ao2_snapshot = ao2_alloc(sizeof(*new_snapshot), NULL);
-	}
-
-	/* Only remove the old cached state if we can insert a new one or the channel is being hung up */
+		ao2_snapshot = ao2_alloc(sizeof(*new_snapshot), channel_snapshot_destroy);
+	}
+
+	/* Only remove the old cached state if we can insert a new one or the channel is hung up */
+	if (ao2_snapshot || is_hungup) {
+		find_flags |= OBJ_UNLINK;
+	}
+
+	/* Lock the cache while replacing the snapshot for this channel. */
 	ao2_lock(channel_state_cache);
-	if (ao2_snapshot || is_hungup) {
-		old_snapshot = ao2_find(channel_state_cache, new_snapshot->name, OBJ_KEY | OBJ_UNLINK);
-	} else {
-		/* Not hanging up and allocation failed.  Leave the old snapshot in place.
-		 * This may cause duplicate events, but it's better than missing an event. */
-		old_snapshot = ao2_find(channel_state_cache, new_snapshot->name, OBJ_KEY);
-	}
+	old_snapshot = ao2_find(channel_state_cache, new_snapshot->name, find_flags);
 
 	/* Link in the new snapshot if available */
 	if (ao2_snapshot) {
-		memcpy(ao2_snapshot, new_snapshot, sizeof(*ao2_snapshot));
+		ast_channel_snapshot_copy(ao2_snapshot, new_snapshot, sizeof(*ao2_snapshot));
 		ao2_link(channel_state_cache, ao2_snapshot);
 		ao2_t_ref(ao2_snapshot, -1, "decrement ref for ao2_snapshot from creation since it is now linked and no longer needed");
 		ao2_snapshot = NULL;
 	}
 	ao2_unlock(channel_state_cache);
 
-	if (!old_snapshot) {
+	/* Generate a Newchannel event when there is no cached state and the channel has not been hung up. */
+	if (!old_snapshot && !is_hungup) {
 		manager_newchannel(new_snapshot);
 	}
 
+	/* Generate a Newstate event when the old state is known and has changed. */
 	if (old_snapshot && new_snapshot->state != old_snapshot->state) {
 		manager_newstate(new_snapshot);
 	}
 
-	if (is_hungup) {
+	/* Generate a Hangup event when the old state is known and the channel has been hung up. */
+	if (old_snapshot && is_hungup) {
 		manager_hangup(new_snapshot);
 	}
 
+	/* Destroy the snapshot removed from the cache.
+	 * The destructor is set in the AO2 object, so no need to do it manually. */
 	if (old_snapshot) {
 		ao2_t_ref(old_snapshot, -1, "decrement ref for old_snapshot from ao2_find");
 		old_snapshot = NULL;

Modified: team/kmoore/channel-state-caching/res/res_security_log.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/channel-state-caching/res/res_security_log.c?view=diff&rev=380842&r1=380841&r2=380842
==============================================================================
--- team/kmoore/channel-state-caching/res/res_security_log.c (original)
+++ team/kmoore/channel-state-caching/res/res_security_log.c Mon Feb  4 22:12:12 2013
@@ -92,6 +92,7 @@
 	case AST_EVENT_IE_PLTYPE_UNKNOWN:
 	case AST_EVENT_IE_PLTYPE_EXISTS:
 	case AST_EVENT_IE_PLTYPE_RAW:
+	case AST_EVENT_IE_PLTYPE_RAW_LOCAL:
 		ast_log(LOG_WARNING, "Unexpected payload type for IE '%s'\n",
 				ast_event_get_ie_type_name(ie_type));
 		break;




More information about the asterisk-commits mailing list