[asterisk-commits] mmichelson: branch mmichelson/atxfer_features r392108 - /team/mmichelson/atxf...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jun 17 16:15:24 CDT 2013


Author: mmichelson
Date: Mon Jun 17 16:15:23 2013
New Revision: 392108

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392108
Log:
Progress a bit on the monitoring thread.

The basic loop is defined, and stubs for all states' enter and next
callbacks are in place. In addition, enums and structs have been defined
(though the structs are currently incomplete).

The next step is to fill in the states' callbacks with more details.


Modified:
    team/mmichelson/atxfer_features/main/bridging_basic.c

Modified: team/mmichelson/atxfer_features/main/bridging_basic.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/atxfer_features/main/bridging_basic.c?view=diff&rev=392108&r1=392107&r2=392108
==============================================================================
--- team/mmichelson/atxfer_features/main/bridging_basic.c (original)
+++ team/mmichelson/atxfer_features/main/bridging_basic.c Mon Jun 17 16:15:23 2013
@@ -407,6 +407,299 @@
 	*transfer_code = ATXFER_ABORT;
 	ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
 	return 0;
+}
+
+enum attended_transfer_state {
+	/* Transfer target is ringing, Transferer is in target bridge */
+	TRANSFER_CALLING_TARGET,
+	/* Transfer target is ringing, Transferer is in transferee bridge */
+	TRANSFER_HESITANT,
+	/* Transfer is aborted, Transferer is in target bridge */
+	TRANSFER_REBRIDGE,
+	/* Transfer is aborted, Transferer is in transferee bridge */
+	TRANSFER_RESUME,
+	/* Transfer has been turned into a three-way call */
+	TRANSFER_THREEWAY,
+	/* The transfer target is up, Transferer is in the target bridge */
+	TRANSFER_CONSULTING,
+	/* The transfer target is up, Transferer is in the transferee bridge */
+	TRANSFER_DOUBLECHECKING,
+	/* The transfer has reached a successful conclusion */
+	TRANSFER_COMPLETE,
+	/* Transfer target is ringing, Transferer has hung up */
+	TRANSFER_BLOND,
+	/* Transfer target did not answer, re-call transferer */
+	TRANSFER_RECALLING,
+	/* Transferer did not answer re-call, re-call transfer target */
+	TRANSFER_RETRANSFER,
+	/* The transfer did not succeed. All parties will disappear */
+	TRANSFER_FAIL,
+};
+
+enum attended_transfer_stimulus {
+	STIMULUS_NONE,
+	STIMULUS_TRANSFEREE_HANGUP,
+	STIMULUS_TRANSFERER_HANGUP,
+	STIMULUS_TARGET_HANGUP,
+	STIMULUS_TARGET_ANSWER,
+	STIMULUS_TIMEOUT,
+	STIMULUS_DTMF_ATXFER_ABORT,
+	STIMULUS_DTMF_ATXFER_COMPLETE,
+	STIMULUS_DTMF_ATXFER_THREEWAY,
+	STIMULUS_DTMF_ATXFER_SWAP,
+};
+
+struct attended_transfer_properties {
+	ast_mutex_t lock;
+	ast_cond_t cond;
+	struct timeval start;
+	struct timeval timeout;
+	enum attended_transfer_stimulus stimulus;
+	enum attended_transfer_state state;
+	int atxferdropcall;
+	int atxfercallbackretries;
+};
+
+static int calling_target_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static enum attended_transfer_state calling_target_next(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return TRANSFER_FAIL;
+}
+
+static int hesitant_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static enum attended_transfer_state hesitant_next(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return TRANSFER_FAIL;
+}
+
+static int rebridge_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static int resume_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static int threeway_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static int consulting_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static enum attended_transfer_state consulting_next(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return TRANSFER_FAIL;
+}
+
+static int double_checking_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static enum attended_transfer_state double_checking_next(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return TRANSFER_FAIL;
+}
+
+static int complete_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static int blond_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static enum attended_transfer_state blond_next(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return TRANSFER_FAIL;
+}
+
+static int recalling_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static enum attended_transfer_state recalling_next(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return TRANSFER_FAIL;
+}
+
+static int retransfer_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+static enum attended_transfer_state retransfer_next(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return TRANSFER_FAIL;
+}
+
+static int fail_enter(struct attended_transfer_properties *properties)
+{
+	/* XXX STUB */
+	return 0;
+}
+
+enum attended_transfer_state_flags {
+	TRANSFER_STATE_IS_TIMED = (1 << 0),
+	TRANSFER_STATE_RESET_TIMER = (1 << 1),
+	TRANSFER_STATE_IS_TERMINAL = (1 << 2),
+};
+
+static struct attended_transfer_state_properties {
+	const char *state_name;
+	int (*enter)(struct attended_transfer_properties *properties);
+	enum attended_transfer_state (*next)(struct attended_transfer_properties *properties);
+	enum attended_transfer_state_flags flags;
+} state_properties [] = {
+	[TRANSFER_CALLING_TARGET] = {
+		.state_name = "Calling Target",
+		.enter = calling_target_enter,
+		.next = calling_target_next,
+		.flags = TRANSFER_STATE_IS_TIMED | TRANSFER_STATE_RESET_TIMER,
+	},
+	[TRANSFER_HESITANT] = {
+		.state_name = "Hesitant",
+		.enter = hesitant_enter,
+		.next = hesitant_next,
+		.flags = TRANSFER_STATE_IS_TIMED,
+	},
+	[TRANSFER_REBRIDGE] = {
+		.state_name = "Rebridge",
+		.enter = rebridge_enter,
+		.flags = TRANSFER_STATE_IS_TERMINAL,
+	},
+	[TRANSFER_RESUME] = {
+		.state_name = "Resume",
+		.enter = resume_enter,
+		.flags = TRANSFER_STATE_IS_TERMINAL,
+	},
+	[TRANSFER_THREEWAY] = {
+		.state_name = "Threeway",
+		.enter = threeway_enter,
+		.flags = TRANSFER_STATE_IS_TERMINAL,
+	},
+	[TRANSFER_CONSULTING] = {
+		.state_name = "Consulting",
+		.enter = consulting_enter,
+		.next = consulting_next,
+	},
+	[TRANSFER_DOUBLECHECKING] = {
+		.state_name = "Double Checking",
+		.enter = double_checking_enter,
+		.next = double_checking_next,
+	},
+	[TRANSFER_COMPLETE] = {
+		.state_name = "Complete",
+		.enter = complete_enter,
+		.flags = TRANSFER_STATE_IS_TERMINAL,
+	},
+	[TRANSFER_BLOND] = {
+		.state_name = "Blond",
+		.enter = blond_enter,
+		.next = blond_next,
+		.flags = TRANSFER_STATE_IS_TIMED,
+	},
+	[TRANSFER_RECALLING] = {
+		.state_name = "Recalling",
+		.enter = recalling_enter,
+		.next = recalling_next,
+		.flags = TRANSFER_STATE_IS_TIMED | TRANSFER_STATE_RESET_TIMER,
+	},
+	[TRANSFER_RETRANSFER] = {
+		.state_name = "Retransfer",
+		.enter = retransfer_enter,
+		.next = retransfer_next,
+		.flags = TRANSFER_STATE_IS_TIMED | TRANSFER_STATE_RESET_TIMER,
+	},
+	[TRANSFER_FAIL] = {
+		.state_name = "Fail",
+		.enter = fail_enter,
+		.flags = TRANSFER_STATE_IS_TERMINAL,
+	},
+};
+
+static void wait_for_stimulus(struct attended_transfer_properties *props)
+{
+	SCOPED_MUTEX(lock, &props->lock);
+
+	while (props->stimulus == STIMULUS_NONE) {
+		if (!(state_properties[props->state].flags & TRANSFER_STATE_IS_TIMED)) {
+			ast_cond_wait(&props->cond, lock);
+		} else {
+			struct timeval timeout;
+			struct timespec timeout_arg;
+
+			if (state_properties[props->state].flags & TRANSFER_STATE_RESET_TIMER) {
+				props->start = ast_tvnow();
+			}
+			timeout = ast_tvadd(props->start, props->timeout);
+			timeout_arg.tv_sec = timeout.tv_sec;
+			timeout_arg.tv_nsec = timeout.tv_usec * 1000;
+
+			if (ast_cond_timedwait(&props->cond, lock, &timeout_arg) == ETIMEDOUT) {
+				props->stimulus = STIMULUS_TIMEOUT;
+			}
+		}
+	}
+}
+
+static __attribute__((unused)) void *attended_transfer_monitor_thread(void *data)
+{
+	struct attended_transfer_properties *props = data;
+
+	for (;;) {
+		if (state_properties[props->state].enter &&
+				state_properties[props->state].enter(props)) {
+			break;
+		}
+
+		if (state_properties[props->state].flags & TRANSFER_STATE_IS_TERMINAL) {
+			break;
+		}
+
+		wait_for_stimulus(props);
+		
+		ast_assert(state_properties[props->state].next != NULL);
+
+		props->state = state_properties[props->state].next(props);
+	}
+
+	return NULL;
 }
 
 /*! \brief Internal built in feature for attended transfers */




More information about the asterisk-commits mailing list