About
FreeSWITCH endpoints are designed to create, handle and destroy media streams.
This page describes sessions and channels from the point of view of writing an extension module for FreeSWITCH.
FreeSWITCH Sessions and Channels
A FreeSWITCH session is equivalent to a call-leg when the session is managed by mod_sofia.
FreeSWITCH manages the establishment and destruction of linked sessions between entities. For those of us from a telephony background, FreeSWITCH performs the functions of a PBX or central office. The following document is written with respect voice calls, but the principles apply to the other types of connections that FreeSWITCH can manage.
The voice entities that we're most familiar with are simple telephones. The modules that handles these are called “endpoints”. The most used endpoint modules are mod_sofia (SIP phones) and mod_skinny (Cisco phones).
As modules, they must have the following entry points to be loaded and unloaded.
-module_load() -module_unload()
Usually a module will also implement two interfaces, as arrays of callback functions. This is how FreeSWITCH communicates with the module.
An endpoint module deals a lot with sessions. A session contains a channel and private data.
This diagram shows containment, when in fact pointers are used.
The channel is the basic entity for one end of a FreeSWITCH call. The most interesting members of a channel are:
-name
-uuid
-direction
-its session (wrapper)
-state
-caller_profile
-flags
-variables
Channel objects manage the flow of media to the outside world. Channels are where the most interesting things happen. The channcel runs through states that represent the state of call setup, the media flow and the call tear down.
A session object wraps a channel in some management overhead, including:
-thread to run the code
-memory pool
-array of codecs
-message queues
-read/write data buffers
So, the session owns the channel, so in a sense the session is the parent of the channel. But the channel is the interesting object.
The session also owns a private object. The author of the module defines what this object contains and what it's used for. In almost all modules, this object is called session->tech_pvt. Some common elements of a tech_pvt are:
-ip addresses involved in the communication channel
-encryption keys for the communication channel
-the external codecs involved in the media flow
Now, returning to the channel object, it's single most important member is its state. The 'state' member is the one that most FreeSWITCH documentation references. This state runs through the sequence CS_NEW, CS_INIT, CS_ROUTING, CS_EXECUTE, CS_HANGUP, CS_REPORTING and CS_DESTROY
. The transitions from one state to the other are handled gracefully by the internals of FS (switch_core_state_machine.c
) unless you intercept these transitions. This state describes the highest level connection status of the channel/session.
The channel object also has two other state members (running_state and callstate) which are hardly used at all in the core of FreeSWITCH and which you probably won't need. The running_state is just used in state transitions, usually holds the “previous state”. The callstate is a more fine-grained version of the state. Callstate has its own getter and setter. If you chose to use the setter, it will fire an event. Callstate include CCS_DOWN, CCS_DIALING, CCS_RINGING, CCS_EARLY, CCS_ACTIVE and CCS_HANGUP.
The state variable is not directly what one would normally use in telephony. Because FreeSWITCH can handle many kinds of media, the state variable is designed to handle the connection status. You need also look at CF_RING_READY, CF_EARLY_MEDIA
and CF_ANSWERED
in order to determine the telephony state.
Here's a table to illustrate some details of the states:
| right after session creation | none | change to |
| create any data structures required for the rest of the session/call | changes to |
|
| inbound: dial tone, accepting digits, ringback
| inbound: uses the caller_profile & the dialplan to pick a destination
| inbound: your module will get a message outbound: your module should call |
| outbound: ringing |
|
|
| outbound: talking |
|
|
| inbound: media flows; talking |
| near_end release: your module should call far_end release: your module will get a callback on |
|
| Changes to |
|
|
| Changes to |
|
| Release any memory |
|
|
Within the channel is a single caller_profile. This contains descriptions of both the caller and callee. The internal sections of FreeSWITCH only use:
-uuid
-caller_id_name, caller_id_number, caller_extension
-dialplan
-destination_number
The channel flags hold extra state information above and beyond the basic 13 states that are held in the state variable. The interesting flags are things like
CF_ANSWERED - Channel is answered
CF_OUTBOUND - Channel is an outbound channel
CF_EARLY_MEDIA - Channel is ready for audio before answer
CF_ORIGINATOR - Channel is an originator
CF_TRANSFER - Channel is being transfered
CF_HOLD - Channel is on hold
CF_GEN_RINGBACK - Channel is generating it's own ringback
CF_RING_READY - Channel is ready to send ringback
CF_BREAK - Channel should stop what it's doing
And a channel has a hash of key-value pairs that can hold all kinds of interesting data related to the channel. These are used extensively by mod_sofia to bind things like 'sip_user_agent' and 'sip_profile_name' to a channel. These key-value pairs can be queried by either the dialplan or LUA processing. They can also be a handy way to accumulate data in preparation for issuing a FreeSWITCH event. See channel variables.