From 21ee5f705a5178c854be8db85b41d737c17afa00 Mon Sep 17 00:00:00 2001
From: Mike Bradeen <mbradeen@sangoma.com>
Date: Tue, 2 May 2023 09:20:22 -0600
Subject: [PATCH] cel: add local optimization begin event

The current AST_CEL_LOCAL_OPTIMIZE event is and has been
triggered on a local optimization end to serve as a flag
indicating the event occurred.  This change adds a second
AST_CEL_LOCAL_OPTIMIZE_BEGIN event for further detail.

Resolves: #52

UpgradeNote: The existing AST_CEL_LOCAL_OPTIMIZE can continue
to be used as-is and the AST_CEL_LOCAL_OPTIMIZE_BEGIN event
can be ignored if desired.

UserNote: The new AST_CEL_LOCAL_OPTIMIZE_BEGIN can be used
by itself or in conert with the existing
AST_CEL_LOCAL_OPTIMIZE to book-end local channel optimizaion.

(cherry picked from commit 8d3d8fcdcd79401dc14c497c251e565fa4481e41)
---
 include/asterisk/cel.h |  4 +++-
 main/cel.c             | 34 ++++++++++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/include/asterisk/cel.h b/include/asterisk/cel.h
index c0b8848dee..5645e8db2a 100644
--- a/include/asterisk/cel.h
+++ b/include/asterisk/cel.h
@@ -73,8 +73,10 @@ enum ast_cel_event_type {
 	AST_CEL_PICKUP = 15,
 	/*! \brief this call was forwarded somewhere else  */
 	AST_CEL_FORWARD = 16,
-	/*! \brief A local channel optimization occurred */
+	/*! \brief A local channel optimization occurred, this marks the end */
 	AST_CEL_LOCAL_OPTIMIZE = 17,
+	/*! \brief A local channel optimization has begun */
+	AST_CEL_LOCAL_OPTIMIZE_BEGIN = 18,
 };
 
 /*!
diff --git a/main/cel.c b/main/cel.c
index 7e78409bba..942a9afa12 100644
--- a/main/cel.c
+++ b/main/cel.c
@@ -102,6 +102,7 @@
 						<enum name="FORWARD"/>
 						<enum name="LINKEDID_END"/>
 						<enum name="LOCAL_OPTIMIZE"/>
+						<enum name="LOCAL_OPTIMIZE_BEGIN"/>
 					</enumlist>
 					</description>
 				</configOption>
@@ -321,6 +322,7 @@ static const char * const cel_event_types[CEL_MAX_EVENT_IDS] = {
 	[AST_CEL_FORWARD]          = "FORWARD",
 	[AST_CEL_LINKEDID_END]     = "LINKEDID_END",
 	[AST_CEL_LOCAL_OPTIMIZE]   = "LOCAL_OPTIMIZE",
+	[AST_CEL_LOCAL_OPTIMIZE_BEGIN]   = "LOCAL_OPTIMIZE_BEGIN",
 };
 
 struct cel_backend {
@@ -1389,9 +1391,11 @@ static void cel_pickup_cb(
 	ast_json_unref(extra);
 }
 
-static void cel_local_cb(
+
+static void cel_local_optimization_cb_helper(
 	void *data, struct stasis_subscription *sub,
-	struct stasis_message *message)
+	struct stasis_message *message,
+	enum ast_cel_event_type event_type)
 {
 	struct ast_multi_channel_blob *obj = stasis_message_data(message);
 	struct ast_channel_snapshot *localone = ast_multi_channel_blob_get_channel(obj, "1");
@@ -1409,10 +1413,27 @@ static void cel_local_cb(
 		return;
 	}
 
-	cel_report_event(localone, AST_CEL_LOCAL_OPTIMIZE, stasis_message_timestamp(message), NULL, extra, NULL);
+	cel_report_event(localone, event_type, stasis_message_timestamp(message), NULL, extra, NULL);
 	ast_json_unref(extra);
 }
 
+static void cel_local_optimization_end_cb(
+	void *data, struct stasis_subscription *sub,
+	struct stasis_message *message)
+{
+	/* The AST_CEL_LOCAL_OPTIMIZE event has always been triggered by the end of optimization.
+	   This can either be used as an indication that the call was locally optimized, or as
+	   the END event in combination with the subsequently added BEGIN event. */
+	cel_local_optimization_cb_helper(data, sub, message, AST_CEL_LOCAL_OPTIMIZE);
+}
+
+static void cel_local_optimization_begin_cb(
+	void *data, struct stasis_subscription *sub,
+	struct stasis_message *message)
+{
+	cel_local_optimization_cb_helper(data, sub, message, AST_CEL_LOCAL_OPTIMIZE_BEGIN);
+}
+
 static void destroy_routes(void)
 {
 	stasis_message_router_unsubscribe_and_join(cel_state_router);
@@ -1555,7 +1576,12 @@ static int create_routes(void)
 
 	ret |= stasis_message_router_add(cel_state_router,
 		ast_local_optimization_end_type(),
-		cel_local_cb,
+		cel_local_optimization_end_cb,
+		NULL);
+
+	ret |= stasis_message_router_add(cel_state_router,
+		ast_local_optimization_begin_type(),
+		cel_local_optimization_begin_cb,
 		NULL);
 
 	if (ret) {
-- 
GitLab