Sip Soft Switch Astri Con Adapted
-
Upload
christopher-garrido-nizama -
Category
Documents
-
view
223 -
download
0
Transcript of Sip Soft Switch Astri Con Adapted
-
7/29/2019 Sip Soft Switch Astri Con Adapted
1/28
Building a SIP softswitch withAsterisk and Asterisk-Java
Monica McArthur
Adapted from my presentation at AstriCon 2007
-
7/29/2019 Sip Soft Switch Astri Con Adapted
2/28
The task at hand
Build a pure SIP softswitch that can perform the following functions:
Answer an inbound call and redirect it to a specified target phonenumber
Rules for determining target number can be complex
Record both legs of the call
Play prerecorded prompts separately to inbound and outbound legs Provide call routing through IVR trees, overflow on busy/no answer,
and voicemail
Save the call detail record to a database for access by applications todo reporting and further data processing
All features can be provisioned in real-time
System must be highly-available and scalable Initial capacity 1250 simultaneous calls
99.99% availability requirement
Scheduled maintenance can be performed with no downtime
-
7/29/2019 Sip Soft Switch Astri Con Adapted
3/28
General solution
Write a routing application in Java to handle routing rules,provisioning changes, and interface with the database and otherapplications
Have the Java application direct a third-party host media processingsystem that provides the actual SIP signaling, RTP media handling,
prompt playing, call recording, and DTMF input
The application servers running the Java routing application are load-balanced by hardware and can be scaled as needed
The host media processing servers are load-balanced by a SIP proxy
server and can be scaled as needed
-
7/29/2019 Sip Soft Switch Astri Con Adapted
4/28
Particular issues
Inbound leg must be able to continue even if outbound leg fails To provide voicemail and overflow routing
Outbound leg must be able to continue after inbound leg hangs up ona connected call
To provide post-call input and play index number for recorded calls
Outbound calls may play a whisper heard only by the target while
the inbound still hears ringback
If there is no whisper, the call must support early media Media begins streaming (initially ringback) before outbound connect and must be
played to inbound
If early media is not streamed to inbound leg, the initial few syllables of the outboundcall may be lost (media clipping)
Ringback must not be included in call recordings
-
7/29/2019 Sip Soft Switch Astri Con Adapted
5/28
Overview of early media issue
In many standard SIP signaling exchanges, the answering user agentmay start generating media before the first agent is ready for it(media clipping)
To avoid media clipping, the answering user agent may send a 183(session progress) and then initiate a one-way media stream at thatpoint
If the initial user agent ignores the media stream sent with the 183and only accesses it after receiving a 200, media clipping will stilloccur
This issue is discussed in RFC 3960: Early Media and Ringing ToneGeneration in the Session Initiation Protocol (SIP)
http://www.rfc-archive.org/getrfc.php?rfc=3960
http://www.rfc-archive.org/getrfc.php?rfc=3960http://www.rfc-archive.org/getrfc.php?rfc=3960http://www.rfc-archive.org/getrfc.php?rfc=3960http://www.rfc-archive.org/getrfc.php?rfc=3960 -
7/29/2019 Sip Soft Switch Astri Con Adapted
6/28
Diagram of SIP signaling with early media
Media path established
Inbound leg Media gateway Outbound leg
INVITE
100 TRYING
183 SESSION PROGRESS
Early media
200 OK
Normal media
Media that can be lost
to clipping
-
7/29/2019 Sip Soft Switch Astri Con Adapted
7/28
Problems with existing solution
Ports are expensive!
Chosen host media platform did not support early media
Dependent on vendor to implement fixes Could take years
Often broke workarounds in place to support other features
-
7/29/2019 Sip Soft Switch Astri Con Adapted
8/28
New solution: Asterisk
Port cost now zero
More port density per server (can easily achieve 150 vs. 125)
Open source allows us to either find bug fixes in the Asteriskcommunity or write our own
FastAGI and AMI provide means for existing Java software to
communicate with Asterisk in ways similar to the previous HMP Only need to replace the vendor-specific code
-
7/29/2019 Sip Soft Switch Astri Con Adapted
9/28
Software architecture with Asterisk
-
7/29/2019 Sip Soft Switch Astri Con Adapted
10/28
How to interface with Asterisk
Could write our own software to interface with FastAGI and AMI
Or could select from a wide variety of existing open source libraries
After review, selected Asterisk-Java
http://asterisk-java.org
http://asterisk-java.org/http://asterisk-java.org/http://asterisk-java.org/http://asterisk-java.org/ -
7/29/2019 Sip Soft Switch Astri Con Adapted
11/28
Asterisk-Java
Open source, free library for Asterisk integration
Hosted in SourceForge
Current version is 0.3
Handles the low-level details of FastAGI and AMI communication
Java code for accessing AGI using Asterisk-Java is structuredsimilarly to servlets
AMI communication is handled through ManagerActions (to send AMIactions) and ManagerEvents (to receive AMI events)
-
7/29/2019 Sip Soft Switch Astri Con Adapted
12/28
Accessing AGI in Asterisk-Java
AGI applications are implemented as subclasses of BaseAgiScript
BaseAgiScript provides convenience methods to send all AGIcommands
AGI scripts are mapped to correct classes in setup code
service() method of BaseAgiScript has two arguments, AgiRequestand AgiChannel
AgiRequest contains information about the call (caller ID, dialeddigits, etc.)
AgiChannel handles the details of the convenience methods
-
7/29/2019 Sip Soft Switch Astri Con Adapted
13/28
Accessing AGI in Asterisk-Java(examples)
public class AGIInbound extends BaseAgiScript {
public void service(AgiRequest request, AgiChannel channel)
throws AgiException {
callID = new Long(getVariable(APP_CALLID"));this.streamFile(greetingFile);
this.streamFile("routing/tone");
this.exec("Record", recordingFilename + ".wav" + "|" + silence
+ "|" + maxduration + "|q");
this.hangup();
Agi script to begin handling call
Code for voicemail
agiMap.put("AGIInbound.agi", new AGIInbound());
SimpleMappingStrategy agiMapping = new SimpleMappingStrategy();
agiMapping.setMappings(agiMap);
agiServer.setMappingStrategy(agiMapping);
Setting up the mapping for AGIInbound
-
7/29/2019 Sip Soft Switch Astri Con Adapted
14/28
Accessing AMI in Asterisk-Java
Subclasses of ManagerAction are provided for each AMI action e.g., OriginateAction, HangupAction, SetVarAction
Instances of actions are sent by using an instance ofManagerConnection
Subclasses of ManagerEvent are provided for each AMI event e.g., DialEvent, HangupEvent, NewChannelEvent
Subclasses of ManagerEventListener are registered to listen on aManagerConnection
Can also create custom events that are subclasses of ManagerEventand register them with the ManagerConnection
-
7/29/2019 Sip Soft Switch Astri Con Adapted
15/28
Accessing AMI in Asterisk-Java(examples)
managerConnection.addEventListener(new
ManagerEventListenerProxy(amiDispatchers.get(routingNode)));
managerConnection.registerUserEventClass(Class.forName(
"astrouting.control.ami.events.ConnectedEvent"));
public class ConnectedEvent extends ManagerEvent {
private String channelName;
private String channelID;
private String userData;
Configure event listener and custom event
Custom ManagerEvent
OriginateAction originateAction = new OriginateAction();originateAction.setChannel(channel);
originateAction.setVariable(APP_CALLID", "" + astCall.getCallID());
originateAction.setAsync(true);
originateAction.setTimeout(1000L*astCall.getCall().getRNATime()+5000L);
managerResponse = managerConnection.sendAction(originateAction);
Create and send OriginateAction
-
7/29/2019 Sip Soft Switch Astri Con Adapted
16/28
Software architecture (detailed)
-
7/29/2019 Sip Soft Switch Astri Con Adapted
17/28
Remaining issues
With this architecture and a plain version of Asterisk, we can provide allof the required features of the softswitch EXCEPT
Having the outbound leg survive after the inbound disconnects Need legs in separate threads
Early media app_dial does provide support for early media, but only with the channel it is running
on
-
7/29/2019 Sip Soft Switch Astri Con Adapted
18/28
Problem 1: having the outbound legsurvive after the inbound disconnects
The straightforward way to handle connecting an inbound leg toanother number is to dial the number using app_dial
Unfortunately, in that case the outbound leg does not survive thehangup of the inbound leg
Need to have each leg living independently (in its own channel) butstill joined together
-
7/29/2019 Sip Soft Switch Astri Con Adapted
19/28
Solution
To get the outbound leg in its own channel: use AMI Originate to get alocal channel, connect to AGI, then use app_dial to make theoutbound call
To join the two channels together: use a patch for bridgingindependent legs
Was bug 5841; in trunk for 1.6
-
7/29/2019 Sip Soft Switch Astri Con Adapted
20/28
Originate on a local channel
First, use AMI OriginateAction to request a local channel that will startin a particular context and go to another context when connected
Syntax is local/s@
Then, launch AGI script from context
In AGI script, use app_dial to make actual call for outbound leg
Check result of app_dial in start context to handle busy/no answer
Perform additional functions on connected leg in context specified forconnection
This is a well-known pattern; see
http://blogs.reucon.com/asterisk-java/2007/04/18/originate_using_asterisk_local_channels.html
http://blogs.reucon.com/asterisk-java/2007/04/18/originate_using_asterisk_local_channels.htmlhttp://blogs.reucon.com/asterisk-java/2007/04/18/originate_using_asterisk_local_channels.htmlhttp://blogs.reucon.com/asterisk-java/2007/04/18/originate_using_asterisk_local_channels.htmlhttp://blogs.reucon.com/asterisk-java/2007/04/18/originate_using_asterisk_local_channels.htmlhttp://blogs.reucon.com/asterisk-java/2007/04/18/originate_using_asterisk_local_channels.html -
7/29/2019 Sip Soft Switch Astri Con Adapted
21/28
Example code for origination
int dialExecResult = exec(Dial, "SIP/" + target + "@nextone|" +
dialTimeout);
String DIALSTATUS = this.getVariable("DIALSTATUS");
if (dialExecResult == 0) {
if ("NOANSWER".equals(DIALSTATUS)) {
astCall.noAnswer();
} else if ("BUSY".equals(DIALSTATUS)) {
astCall.busy();}
// etc. for CONGESTION, CHANUNAVAIL, CANCEL, HANGUP, default
}
Configure and send OriginateActionOriginateAction originateAction = new OriginateAction();
originateAction.setChannel("Local/s@ob-agi-dial");
originateAction.setApplication("Agi");
originateAction.setData("agi://" + agiServer+
":4573/AGIOutboundConnect.agi");
managerResponse = managerConnection.sendAction(originateAction);
Launch app_dial and check result
-
7/29/2019 Sip Soft Switch Astri Con Adapted
22/28
Bridge patch
Bridge patch was originally submitted with bug 5841: Bridge twochannels via a Dialplan App or an AMI event
Provides a Bridge() application for dialplan/AGI and an AMI Bridgeaction that will bridge the current channel with another specifiedchannel that already exists
Used to bridge the inbound leg with the connected outbound legobtained by app_dial
Patch we used was bridge-trunk-rev48286.patch
Code is now included in 1.6 trunk See http://bugs.digium.com/view.php?id=5841 for details
http://bugs.digium.com/view.php?id=5841http://bugs.digium.com/view.php?id=5841 -
7/29/2019 Sip Soft Switch Astri Con Adapted
23/28
Problem 2: early media
app_dial provides support for early media, but only to its inbound leg
In this architecture, the inbound leg is a local channel and the actualinbound leg does not receive media from the outbound leg until theyare joined using Bridge()
In order to provide early media to the inbound leg, app_dial needs toreturn if SIP 183 (session progress) is received
Since calls with whisper cannot use early media, whether app_dialreturns on SIP 183 needs to be configurable
In order to avoid recording the ringback when early media is used, theJava application needs to know when the SIP 200 (OK) is receivedafter app_dial connects on SIP 183
-
7/29/2019 Sip Soft Switch Astri Con Adapted
24/28
Example code to use bridge patch
public void onManagerEvent(ManagerEvent event) {
else if (event instanceof DialEvent) {
astCall = AstRoutingController.getController().
getAstCallByChannel(event.getSrc());
astCall.setObAstChannel(event.getDestination());
}
Get outbound channel ID from DialEvent
exec("Bridge", astCall.getObAstChannel());
Execute bridge
-
7/29/2019 Sip Soft Switch Astri Con Adapted
25/28
Solution: app_dial and channel patch
This required an original patch
Not yet submitted to Asterisk; will consider based on demand
app_dial.c changed to have new argument which specifies whether toconnect on SIP 183 if received
app_dial.c also stores which signal (PROGRESS/183 or ANSWER/200)it actually connected on SIP spec does not require answering user agent to send 183
channel.c changed to send custom AMI event on receipt of answer Used to determine time to start recording if app_dial connected on 183
-
7/29/2019 Sip Soft Switch Astri Con Adapted
26/28
Example code to use the new patch
String dialExecString = "SIP/" + target + "@nextone|" + dialTimeout;
if(astCall.earlyMedia())
dialExecString += ||1";
int dialExecResult = exec(Dial, dialExecString);
public void onManagerEvent(ManagerEvent event) {
else if (event instanceof ConnectedEvent) {
astCall = AstRoutingController.getController().
getAstCallByChannel(event.getChannelName());
astCall.connectSignaled();
}
Call app_dial with new argument
Receive notice of connect
String connectedSignal = getVariable("CONNECTED_SIGNAL");if("PROGRESS".equals(connectedSignal)) {
// handle early media
} else {
// handle normal flow
}
Check channel variable
-
7/29/2019 Sip Soft Switch Astri Con Adapted
27/28
-
7/29/2019 Sip Soft Switch Astri Con Adapted
28/28
Summary of best practices learned
Go into an AGI script in a context immediately
Use AMI events (hangup events, dial events, new events as needed)to keep track of call state and handle graceful hangups
To get an outbound leg in its own thread, originate on a local channel
and then use app_dial (called from an AGI script) to make the actualoutbound call