FreeSwitch状态机静态接口分析

 

        本文从静态数据结构的视角描述FreeSwitch的状态机。   

        FreeSwitch core实现了一个有限状态机。每一路呼叫的一条腿,都由一个状态机实例维护。状态机定义接口在freeswitch-1.8.7\src\include\switch_types.h文件中

/*!
  \enum switch_channel_state_t
  \brief Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are often overridden by specific apps)
CS_NEW       - Channel is newly created.
CS_INIT      - Channel has been initialized.
CS_ROUTING   - Channel is looking for an extension to execute.
CS_SOFT_EXECUTE  - Channel is ready to execute from 3rd party control.
CS_EXECUTE   - Channel is executing it's dialplan.
CS_EXCHANGE_MEDIA  - Channel is exchanging media with another channel.
CS_PARK      - Channel is accepting media awaiting commands.
CS_CONSUME_MEDIA		 - Channel is consuming all media and dropping it.
CS_HIBERNATE - Channel is in a sleep state.
CS_RESET 	 - Channel is in a reset state.
CS_HANGUP    - Channel is flagged for hangup and ready to end.
CS_REPORTING - Channel is ready to collect call detail.
CS_DESTROY      - Channel is ready to be destroyed and out of the state machine.
*/ typedef enum { CS_NEW, CS_INIT, CS_ROUTING, CS_SOFT_EXECUTE, CS_EXECUTE, CS_EXCHANGE_MEDIA, CS_PARK, CS_CONSUME_MEDIA, CS_HIBERNATE, CS_RESET, CS_HANGUP, CS_REPORTING, CS_DESTROY, CS_NONE } switch_channel_state_t;

状态机接口

外围接口

        状态机接口是一张回调函数表,需要处理状态的模块可以实现自己的接口回调函数并注册。状态机状态迁移时,会挨个调用所有已注册的state_handler。

/*! \brief A table of functions to execute at various states
 */
	typedef enum {
	SWITCH_SHN_ON_INIT,
	SWITCH_SHN_ON_ROUTING,
	SWITCH_SHN_ON_EXECUTE,
	SWITCH_SHN_ON_HANGUP,
	SWITCH_SHN_ON_EXCHANGE_MEDIA,
	SWITCH_SHN_ON_SOFT_EXECUTE,
	SWITCH_SHN_ON_CONSUME_MEDIA,
	SWITCH_SHN_ON_HIBERNATE,
	SWITCH_SHN_ON_RESET,
	SWITCH_SHN_ON_PARK,
	SWITCH_SHN_ON_REPORTING,
	SWITCH_SHN_ON_DESTROY
} switch_state_handler_name_t;

struct switch_state_handler_table {
	/*! executed when the state changes to init */
	switch_state_handler_t on_init;
	/*! executed when the state changes to routing */
	switch_state_handler_t on_routing;
	/*! executed when the state changes to execute */
	switch_state_handler_t on_execute;
	/*! executed when the state changes to hangup */
	switch_state_handler_t on_hangup;
	/*! executed when the state changes to exchange_media */
	switch_state_handler_t on_exchange_media;
	/*! executed when the state changes to soft_execute */
	switch_state_handler_t on_soft_execute;
	/*! executed when the state changes to consume_media */
	switch_state_handler_t on_consume_media;
	/*! executed when the state changes to hibernate */
	switch_state_handler_t on_hibernate;
	/*! executed when the state changes to reset */
	switch_state_handler_t on_reset;
	/*! executed when the state changes to park */
	switch_state_handler_t on_park;
	/*! executed when the state changes to reporting */
	switch_state_handler_t on_reporting;
	/*! executed when the state changes to destroy */
	switch_state_handler_t on_destroy;
	int flags;
	void *padding[10];
};

状态机内部标准接口

        除了外围实现的接口之外,在freeswitch-1.8.7\src\switch_core_state_machine.c里,还实现了一套核心的标准状态处理接口,这就是状态机实现代码中的switch_core_standard_on_XXX这些接口。

 

 

状态机关联的数据结构

Channel

        Channel结构里包含了一个 switch_state_handler_table_t 的列表,维护Channel级别的状态处理回调函数表。

struct switch_channel {
	char *name;
	switch_call_direction_t direction;
	switch_call_direction_t logical_direction;
	switch_queue_t *dtmf_queue;
	switch_queue_t *dtmf_log_queue;
	switch_mutex_t*dtmf_mutex;
	switch_mutex_t *flag_mutex;
	switch_mutex_t *state_mutex;
	switch_mutex_t *thread_mutex;
	switch_mutex_t *profile_mutex;
	switch_core_session_t *session;
	switch_channel_state_t state;
	switch_channel_state_t running_state;
	switch_channel_callstate_t callstate;
	uint32_t flags[CF_FLAG_MAX];
	uint32_t caps[CC_FLAG_MAX];
	uint8_t state_flags[CF_FLAG_MAX];
	uint32_t private_flags;
	switch_caller_profile_t *caller_profile;
	const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];

    .........
}

      Channel实现中,提供了以下接口用于操作Channel中的状态机函数表:

/*!
  \brief add a state handler table to a given channel
  \param channel channel on which to add the state handler table
  \param state_handler table of state handler functions
  \return the index number/priority of the table negative value indicates failure
*/
SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler);

/*!
  \brief clear a state handler table from a given channel
  \param channel channel from which to clear the state handler table
  \param state_handler table of state handler functions
*/
SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler);

/*!
  \brief Retrieve an state handler tablefrom a given channel at given index level
  \param channel channel from which to retrieve the state handler table
  \param index the index of the state handler table (start from 0)
  \return given channel's state handler table at given index or NULL if requested index does not exist.
*/
SWITCH_DECLARE(const switch_state_handler_table_t *) switch_channel_get_state_handler(switch_channel_t *channel, int index);

此外,Channel还提供了设置状态的操作接口:

/*!
  \brief Set the current state of a channel
  \param channel channel to set state of
  \param state new state
  \return current state of channel after application of new state
*/
#define switch_channel_set_state(channel, state) switch_channel_perform_set_state(channel, __FILE__, __SWITCH_FUNC__, __LINE__, state)

switch_runtime

        switch_runtime就FreeSwitch core维护的内核运行时数据,这里也维护了一张switch_state_handler_table_t 的列表,这一层对应的核心层动态添加的状态处理回调。

struct switch_runtime {
	switch_time_t initiated;
	switch_time_t reference;
	int64_t offset;
	switch_event_t *global_vars;
	switch_hash_t *mime_types;
	switch_hash_t *mime_type_exts;
	switch_hash_t *ptimes;
	switch_memory_pool_t *memory_pool;
	const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];
    .........
}

        同样的内核层提供了对这个函数表的操作接口:

SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler)
{
	int index, tmp_index = 0;
	const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 };

	switch_mutex_lock(runtime.global_mutex);

	for (index = 0; index < runtime.state_handler_index; index++) {
		const switch_state_handler_table_t *cur = runtime.state_handlers[index];
		runtime.state_handlers[index] = NULL;
		if (cur == state_handler) {
			continue;
		}
		tmp[tmp_index++] = cur;
	}

	runtime.state_handler_index = 0;

	for (index = 0; index < tmp_index; index++) {
		runtime.state_handlers[runtime.state_handler_index++] = tmp[index];
	}
	switch_mutex_unlock(runtime.global_mutex);
}


SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler)
{
	int index;

	switch_mutex_lock(runtime.global_mutex);
	index = runtime.state_handler_index;

	if (index > (SWITCH_MAX_STATE_HANDLERS - 1)) {
		index = -1;
	} else {
		runtime.state_handlers[index] = state_handler;
		runtime.state_handler_index++;
	}

	switch_mutex_unlock(runtime.global_mutex);
	return index;
}

SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index)
{

	if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {
		return NULL;
	}

	return runtime.state_handlers[index];
}

switch_endpoint_interface

         在endpoint 接口中,包含了一个switch_state_handler_table_t 指针。endpoint层的状态处理handler,是驱动状态机的关键接口,在FS中称为driver_state_handler。

struct switch_endpoint_interface {
	/*! the interface's name */
	const char *interface_name;

	/*! channel abstraction methods */
	switch_io_routines_t *io_routines;

	/*! state machine methods */
	switch_state_handler_table_t *state_handler;

	/*! private information */
	void *private_info;

	switch_thread_rwlock_t *rwlock;
	int refs;
	switch_mutex_t *reflock;

	/* parent */
	switch_loadable_module_interface_t *parent;

	/* to facilitate linking */
	struct switch_endpoint_interface *next;

	switch_core_recover_callback_t recover_callback;

};

比如在sofia模块里,实例化了全局对象sofia_event_handlers:

switch_state_handler_table_t sofia_event_handlers = {
	/*.on_init */ sofia_on_init,
	/*.on_routing */ sofia_on_routing,
	/*.on_execute */ sofia_on_execute,
	/*.on_hangup */ sofia_on_hangup,
	/*.on_exchange_media */ sofia_on_exchange_media,
	/*.on_soft_execute */ sofia_on_soft_execute,
	/*.on_consume_media */ NULL,
	/*.on_hibernate */ sofia_on_hibernate,
	/*.on_reset */ sofia_on_reset,
	/*.on_park */ NULL,
	/*.on_reporting */ NULL,
	/*.on_destroy */ sofia_on_destroy
};

并在模块初始化时为接口赋值:

	sofia_endpoint_interface->io_routines = &sofia_io_routines;
	sofia_endpoint_interface->state_handler = &sofia_event_handlers;
	sofia_endpoint_interface->recover_callback = sofia_recover_callback;

 

状态机核心

        整个状态机的核心代码封装在switch_core_session_run()函数里。它就是个循环体:

while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) {
    ......
}

        只要状态不是CS_DESTROY,它就一直执行。里面有一个长长的switch...case...语句,根据当前的状态,执行不同的代码片段。

STATE_MACRO宏

         这个宏,对不同状态下状态机的执行动作做了统一的封装,简化了代码逻辑。这个宏很长很复杂,但是它概括起来就做了一件事:调用各个注册的状态handler。

  1. 首先是driver_state_handler,即endpoint那一层的handler
  2. 然后是switch_channel_get_state_handler,即channel层的handler
  3. 再然后是switch_core_get_state_handler,即core一层的
  4. 最后是状态机本身最核心的状态处理,即switch_core_standard_on_XXX

 

你可能感兴趣的:(FreeSWITCH)