com.orderlysoftware.orderlycalls.asterisk.agi
Class AGIConnection

java.lang.Object
  extended by com.orderlysoftware.orderlycalls.asterisk.agi.AGIConnection
All Implemented Interfaces:
java.lang.Runnable

public class AGIConnection
extends java.lang.Object
implements java.lang.Runnable

AGIConnection objects represent individual calls coming from the FastAGI source (Asterisk).

Asterisk sends a variety of information with the call to the AGIServer. These properties are stored in the agiProperties property. The various other methods are wrappers for FastAGI calls, which execute on the Asterisk server.

All FastAGI calls block until completion.

Author:
Matt King, M.A. Oxon.

Constructor Summary
AGIConnection()
          Creates an uninitialised AGIConnection object.
AGIConnection(java.net.Socket connection, AGIServer server, AGIProcessor processor)
          Initialises the object in preparation for read from Asterisk.
 
Method Summary
 int answer()
          Answers channel if not already in answer state.
static char asciiToChar(int i)
          Converts an ASCII value to a java char.
 int channelStatus()
          Gets the status of the current channel.
 int channelStatus(java.lang.String channelName)
          Returns the status of the specified channel.
static int charToInt(char c)
          Convert a DTMF character to a number.
 void clean()
          Closes any connections without throwing an exception.
 int databaseDel(java.lang.String family, java.lang.String key)
          Deletes an entry in the Asterisk database for a given family and key.
 int databaseDelTree(java.lang.String family)
          Deletes a family in the Asterisk database.
 int databaseDelTree(java.lang.String family, java.lang.String keyTree)
          Deletes a keytree within a specific family in the Asterisk database.
 java.lang.String databaseGet(java.lang.String family, java.lang.String key)
          Retrieves an entry in the Asterisk database for a given family and key.
 int databasePut(java.lang.String family, java.lang.String key, java.lang.String value)
          Adds or updates an entry in the Asterisk database.
 java.lang.String exec(java.lang.String application, java.lang.String options)
          Executes application with given options.
static AGIConnection getAGIConnection(java.net.Socket connection, AGIServer server, AGIProcessor processor)
          Gets an AGIConnection object from the pool, and initialises it.
 java.util.HashMap getAGIProperties()
          Retrieves the properties for this call as received from Asterisk.
 java.lang.String getAGIProperty(java.lang.String name)
          Gets a particular property for this call.
 java.lang.String getData(java.lang.String filename)
           
 java.lang.String getData(java.lang.String filename, long timeout)
           
 java.lang.String getData(java.lang.String filename, long timeout, int digits)
          Stream the given file, and recieve DTMF data.
 AGIServer getServer()
          Gets the AGIServer that received this connection.
 java.net.Socket getSocket()
           
 java.lang.String getVariable(java.lang.String variableName)
          Gets an Asterisk variable.
 int hangUp()
          Hangs up the call.
 int hangUp(java.lang.String channelName)
          Hangs up a particular channel.
 void init(java.net.Socket connection, AGIServer server, AGIProcessor processor)
          Initialises a pre-existing AGIConnection object.
 boolean isTimedOut()
          Determines whether the last FastAGI call timed out.
 void noop()
          Does nothing.
 char receiveChar(long timeout)
          Receives a character of text on a channel.
 int recordFile(java.lang.String filename, java.lang.String format, java.lang.String escapeDigits, long timeout, boolean beep)
           
 int recordFile(java.lang.String filename, java.lang.String format, java.lang.String escapeDigits, long timeout, boolean beep, int silence)
           
 int recordFile(java.lang.String filename, java.lang.String format, java.lang.String escapeDigits, long timeout, long offsetSamples, boolean beep)
           
 int recordFile(java.lang.String filename, java.lang.String format, java.lang.String escapeDigits, long timeout, long offsetSamples, boolean beep, int silence)
          Record to a file until a given dtmf digit in the sequence is received.
 void run()
          Reads the properties and runs the processor.
 int sayDigits(java.lang.String digits, java.lang.String escapeDigits)
          Say a given digit string, returning early if any of the given DTMF digits are received on the channel.
 int sayNumber(java.lang.String number, java.lang.String escapeDigits)
          Say a given number, returning early if any of the given DTMF digits are received on the channel.
 int sayPhonetic(java.lang.String text, java.lang.String escapeDigits)
          Say a given character string with phonetics, returning early if any of the given DTMF digits are received on the channel.
 int sayTime(long time, java.lang.String escapeDigits)
          Say a given time, returning early if any of the given DTMF digits are received on the channel.
 int sendImage(java.lang.String image)
          Sends the given image on a channel.
 int sendText(java.lang.String text)
          Sends the given text on a channel.
 int setAutoHangup(int seconds)
          Cause the channel to automatically hangup in the future.
 int setCallerID(java.lang.String idSpecification)
          Changes the callerId of the current channel.
 int setContext(java.lang.String newContext)
          Sets the context for continuation upon exiting the application.
 int setExtension(java.lang.String newExtension)
          Changes the extension for continuation upon exiting the application
 int setMusic(boolean enable)
          Enables/Disables the music on hold generator with the default music class.
 int setMusic(boolean enable, java.lang.String music)
          Enables/Disables the music on hold generator.
 int setPriority(java.lang.String newPriority)
          Changes the priority (the number attached to the extension in extensions.conf) for continuation upon exiting the application.
 void setServer(AGIServer server)
           
 void setSocket(java.net.Socket socket)
           
 int setVariable(java.lang.String name, java.lang.String value)
          Sets an Asterisk variable
 int streamFile(java.lang.String filename)
          Send the given file, without interrupt.
 int streamFile(java.lang.String filename, java.lang.String escapeDigits)
          Send the given file, allowing playback to be interrupted by the given digits, if any.
 int streamFile(java.lang.String filename, java.lang.String escapeDigits, long sampleOffset)
          Send the given file, allowing playback to be interrupted by the given digits, if any.
 int tddMode(boolean enable)
          Enable/Disable TDD transmission/reception on a channel.
 int verbose(java.lang.String message, java.lang.String level)
          Sends text to the console via verbose message system.
 int waitForDigit(long timeout)
          Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

AGIConnection

public AGIConnection()
Creates an uninitialised AGIConnection object.

Required for use with ObjectPool.


AGIConnection

public AGIConnection(java.net.Socket connection,
                     AGIServer server,
                     AGIProcessor processor)
Initialises the object in preparation for read from Asterisk.

Called automatically by AGIServer for you.

Parameters:
connection - The socket representing this call.
server - The AGIServer that is managing this connection.
processor - The processor to run.
Method Detail

getAGIProperties

public java.util.HashMap getAGIProperties()
Retrieves the properties for this call as received from Asterisk.

Returns:
HashMap containing all available properties.
See Also:
for a list of available properties.

init

public void init(java.net.Socket connection,
                 AGIServer server,
                 AGIProcessor processor)
Initialises a pre-existing AGIConnection object.

Parameters:
connection - The socket connected to Asterisk.
server - The AGIServer that received the connection.
processor - The AGIProcessor that will be used to process the call.

getAGIConnection

public static AGIConnection getAGIConnection(java.net.Socket connection,
                                             AGIServer server,
                                             AGIProcessor processor)
Gets an AGIConnection object from the pool, and initialises it.

Parameters:
connection - The socket connected to Asterisk.
server - The AGIServer that received the connection.
processor - The AGIProcessor that will be used to process the call.
Returns:
an initialised AGIConnection object.

getAGIProperty

public java.lang.String getAGIProperty(java.lang.String name)
Gets a particular property for this call.

The "agi_channel" and "agi_uniqueid" properties are useful for producing integrated AGI and Manager applications.

Complete keys list (with examples):

Parameters:
name - the name of the property to get.
Returns:
the value of the property.

isTimedOut

public boolean isTimedOut()
Determines whether the last FastAGI call timed out.

Method calls may time out while waiting for digits from the caller, for instance.

Use this method to check for timeouts.

Returns:
true if the last call timed out, false otherwise.

run

public void run()
Reads the properties and runs the processor.

Called automatically by AGIServer for you.

Specified by:
run in interface java.lang.Runnable

answer

public int answer()
           throws java.io.IOException
Answers channel if not already in answer state.

Returns:
Returns -1 on channel failure, or 0 if successful.
Throws:
java.io.IOException - if the caller hangs up before answer.

hangUp

public int hangUp()
           throws java.io.IOException
Hangs up the call.

Does NOT automatically close socket.

Returns:
Throws:
java.io.IOException

hangUp

public int hangUp(java.lang.String channelName)
           throws java.io.IOException
Hangs up a particular channel.

Parameters:
channelName - The name of the channel to hang up.
Returns:
Throws:
java.io.IOException

setAutoHangup

public int setAutoHangup(int seconds)
                  throws java.io.IOException
Cause the channel to automatically hangup in the future.

Of course it can be hungup before then as well (by the caller).

Setting seconds to zero will cause the autohangup feature to be disabled on this channel.

Parameters:
seconds - the amount of time to wait before hanging up.
Returns:
Throws:
java.io.IOException

noop

public void noop()
          throws java.io.IOException
Does nothing.

Why do we even bother? :-)

Throws:
java.io.IOException

channelStatus

public int channelStatus()
                  throws java.io.IOException
Gets the status of the current channel.

Returns:
the status of the current channel.
Throws:
java.io.IOException

channelStatus

public int channelStatus(java.lang.String channelName)
                  throws java.io.IOException
Returns the status of the specified channel. If no channel name is given the returns the status of the current channel.

Parameters:
channelName - the channel to query (null for current channel)
Returns:
0 Channel is down and available
1 Channel is down, but reserved
2 Channel is off hook
3 Digits (or equivalent) have been dialed
4 Line is ringing
5 Remote end is ringing
6 Line is up
7 Line is busy
Throws:
java.io.IOException

exec

public java.lang.String exec(java.lang.String application,
                             java.lang.String options)
                      throws java.io.IOException
Executes application with given options.

Parameters:
application - The application to execute.
options - The options to send it.
Returns:
whatever the application returns, or "-2" on failure to find application
Throws:
java.io.IOException

waitForDigit

public int waitForDigit(long timeout)
                 throws java.io.IOException
Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.

Parameters:
timeout - Use -1 for the timeout value if you desire the call to block indefinitely.
Returns:
-1 on channel failure, 0 if no digit is received in the timeout, or the numerical ASCII value of the digit if one is received.
Throws:
java.io.IOException - if the caller hangs up.
See Also:
asciiToChar(int)

asciiToChar

public static char asciiToChar(int i)
Converts an ASCII value to a java char.

Just in case anyone's not sure how to do this.

Parameters:
i - the ASCII value, e.g. 53
Returns:
the java char, e.g. '5'.

charToInt

public static int charToInt(char c)
Convert a DTMF character to a number.

Parameters:
c - the char to convert, '0','1','2','#' etc.
Returns:
10 for '*', 11 for '#', number otherwise (-1 invalid).

databasePut

public int databasePut(java.lang.String family,
                       java.lang.String key,
                       java.lang.String value)
                throws java.io.IOException
Adds or updates an entry in the Asterisk database.

Parameters:
family - The family of keys containing the key.
key - The key to update.
value - The value to set it to.
Returns:
1 if succesful, 0 otherwise
Throws:
java.io.IOException

databaseGet

public java.lang.String databaseGet(java.lang.String family,
                                    java.lang.String key)
                             throws java.io.IOException
Retrieves an entry in the Asterisk database for a given family and key.

Parameters:
family - The family of keys containing the key.
key - The key to get the value for.
Returns:
value, or null if no value is attached to key.
Throws:
java.io.IOException

databaseDel

public int databaseDel(java.lang.String family,
                       java.lang.String key)
                throws java.io.IOException
Deletes an entry in the Asterisk database for a given family and key.

Parameters:
family - The family of keys containing the key.
key - The key to delete.
Returns:
Returns 1 if succesful, 0 otherwise
Throws:
java.io.IOException

databaseDelTree

public int databaseDelTree(java.lang.String family)
                    throws java.io.IOException
Deletes a family in the Asterisk database.

Parameters:
family - The family of keys to delete.
Returns:
1 if succesful, 0 otherwise
Throws:
java.io.IOException

databaseDelTree

public int databaseDelTree(java.lang.String family,
                           java.lang.String keyTree)
                    throws java.io.IOException
Deletes a keytree within a specific family in the Asterisk database.

Parameters:
family - The family of keys containing the key tree.
keyTree - The tree of keys to delete.
Returns:
1 if successful, 0 otherwise
Throws:
java.io.IOException

clean

public void clean()
Closes any connections without throwing an exception.

Will cause Asterisk to proceed to next priority line in extensions.conf, unless this has been overriden by calls to setContext(java.lang.String), setExtension(java.lang.String)and/or setPriority(java.lang.String)

Also frees this object for reuse by the system, so don't use it after calling clean()

Throws:
java.io.IOException

getVariable

public java.lang.String getVariable(java.lang.String variableName)
                             throws java.io.IOException
Gets an Asterisk variable.

Parameters:
variableName - the name of the variable to get.
Returns:
the variable contents, or null if variable is not set.
Throws:
java.io.IOException

getData

public java.lang.String getData(java.lang.String filename)
                         throws java.io.IOException
Throws:
java.io.IOException

getData

public java.lang.String getData(java.lang.String filename,
                                long timeout)
                         throws java.io.IOException
Throws:
java.io.IOException

getData

public java.lang.String getData(java.lang.String filename,
                                long timeout,
                                int digits)
                         throws java.io.IOException
Stream the given file, and recieve DTMF data.

Parameters:
filename - the file to stream
timeout - how long to wait for digits.
digits - the maximum number of digits to receive
Returns:
Returns the digits recieved from the channel at the other end.
Throws:
java.io.IOException - if the connection is lost.

receiveChar

public char receiveChar(long timeout)
                 throws java.io.IOException
Receives a character of text on a channel.

Specify timeout to be the maximum time to wait for input in milliseconds.

Most channels do not support the reception of text.

Parameters:
timeout - set to 0 or -1 to wait indefinitely.
Returns:
Returns the decimal value of the character if one is received, or 0 if the channel does not support text reception. Returns -1 only on error/hangup.

PostCondition: Check for timeout by calling isTimedOut()

Throws:
java.io.IOException - if the connection is lost.

recordFile

public int recordFile(java.lang.String filename,
                      java.lang.String format,
                      java.lang.String escapeDigits,
                      long timeout,
                      boolean beep,
                      int silence)
               throws java.io.IOException
Throws:
java.io.IOException

recordFile

public int recordFile(java.lang.String filename,
                      java.lang.String format,
                      java.lang.String escapeDigits,
                      long timeout,
                      long offsetSamples,
                      boolean beep)
               throws java.io.IOException
Throws:
java.io.IOException

recordFile

public int recordFile(java.lang.String filename,
                      java.lang.String format,
                      java.lang.String escapeDigits,
                      long timeout,
                      boolean beep)
               throws java.io.IOException
Throws:
java.io.IOException

recordFile

public int recordFile(java.lang.String filename,
                      java.lang.String format,
                      java.lang.String escapeDigits,
                      long timeout,
                      long offsetSamples,
                      boolean beep,
                      int silence)
               throws java.io.IOException
Record to a file until a given dtmf digit in the sequence is received.

Parameters:
filename - The name of the file to record (without extension).
format - The format will specify what kind of file will be recorded.
escapeDigits - DTMF digits that will cause the recording to stop.
timeout - is the maximum record time in milliseconds, or -1 for no timeout.
offsetSamples - is optional, and if provided will seek to the offset without exceeding the end of the file.
beep - Play a beep before recording.
silence - The number of seconds of silence allowed before the function returns despite the lack of dtmf digits or reaching timeout.
Returns:
-1 on hangup or error, or the ASCII value of the digit pressed.
Throws:
java.io.IOException

sayDigits

public int sayDigits(java.lang.String digits,
                     java.lang.String escapeDigits)
              throws java.io.IOException
Say a given digit string, returning early if any of the given DTMF digits are received on the channel.

"101" is said as one-zero-one.

Parameters:
digits - The digits to say.
escapeDigits - DTMF digits that when pressed will abort playback.
Returns:
0 if playback completes without a digit being pressed, or the ASCII value of the digit if one was pressed, or -1 on error/hangup.
Throws:
java.io.IOException - if the connection is lost.

sayNumber

public int sayNumber(java.lang.String number,
                     java.lang.String escapeDigits)
              throws java.io.IOException
Say a given number, returning early if any of the given DTMF digits are received on the channel.

"101" is said as one-hundred-and-one

Parameters:
number - the number to say.
escapeDigits - DTMF digits that when pressed will abort playback.
Returns:
0 if playback completes without a digit being pressed, or the ASCII value of the digit if one was pressed, or -1 on error/hangup.
Throws:
java.io.IOException - if the connection is lost.

sayPhonetic

public int sayPhonetic(java.lang.String text,
                       java.lang.String escapeDigits)
                throws java.io.IOException
Say a given character string with phonetics, returning early if any of the given DTMF digits are received on the channel.

Parameters:
text - The words to say
escapeDigits - DTMF digits that will abort playback.
Returns:
Returns 0 if playback completes without a digit being pressed, or the ASCII value of the digit if one was pressed, or -1 on error/hangup.
Throws:
java.io.IOException - if the connection is lost.

sayTime

public int sayTime(long time,
                   java.lang.String escapeDigits)
            throws java.io.IOException
Say a given time, returning early if any of the given DTMF digits are received on the channel.

Java Date and Timestamp times are stored in milliseconds, and so can be said by calling sayTime(date.getTime()/1000, null)

Parameters:
time - is number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
escapeDigits - DTMF digits that abort playback.
Returns:
Returns 0 if playback completes without a digit being pressed, or the ASCII value of the digit if one was pressed, or -1 on error/hangup.
Throws:
java.io.IOException - if the connection is closed.

sendImage

public int sendImage(java.lang.String image)
              throws java.io.IOException
Sends the given image on a channel. Most channels do not support the transmission of images. Image names should not include extensions.

Parameters:
image - the image to send
Returns:
0 if image is sent, or if the channel does not support image transmission. Returns -1 only on error/hangup.
Throws:
java.io.IOException

sendText

public int sendText(java.lang.String text)
             throws java.io.IOException
Sends the given text on a channel. Most channels do not support the transmission of text.

Parameters:
text - to send
Returns:
0 if text is sent, or if the channel does not support text transmission, or -1 on error or hangup.
Throws:
java.io.IOException - if the connection is lost.

setCallerID

public int setCallerID(java.lang.String idSpecification)
                throws java.io.IOException
Changes the callerId of the current channel.

Do not enclose idSpecification in quotes - this is done for you.

Parameters:
newCallerId -
Returns:
Throws:
java.io.IOException

setContext

public int setContext(java.lang.String newContext)
               throws java.io.IOException
Sets the context for continuation upon exiting the application.

Parameters:
newContext - The Context in which to continue when the socket is closed.
Returns:
Throws:
java.io.IOException

setExtension

public int setExtension(java.lang.String newExtension)
                 throws java.io.IOException
Changes the extension for continuation upon exiting the application

Parameters:
newExtension - The extension at which to continue when the socket closes.
Returns:
Throws:
java.io.IOException

setPriority

public int setPriority(java.lang.String newPriority)
                throws java.io.IOException
Changes the priority (the number attached to the extension in extensions.conf) for continuation upon exiting the application.

Parameters:
newPriority - The extension priority at which to continue when the socket closes.
Returns:
Throws:
java.io.IOException

setMusic

public int setMusic(boolean enable)
             throws java.io.IOException
Enables/Disables the music on hold generator with the default music class.

Parameters:
enable - true to start playing music.
Returns:
0 always.
Throws:
java.io.IOException

setMusic

public int setMusic(boolean enable,
                    java.lang.String music)
             throws java.io.IOException
Enables/Disables the music on hold generator.

Parameters:
enable - true to start playing music.
music - The name of the music to play (must be defined in asterisk's conf).
Returns:
0 always.
Throws:
java.io.IOException

setVariable

public int setVariable(java.lang.String name,
                       java.lang.String value)
                throws java.io.IOException
Sets an Asterisk variable

Parameters:
name - The name of the variable.
value - The value to set it to.
Returns:
Throws:
java.io.IOException

streamFile

public int streamFile(java.lang.String filename)
               throws java.io.IOException
Send the given file, without interrupt.

The file must exist in the Asterisk sounds directory (usually /var/lib/asterisk/sounds). Remember, the file extension must not be included in the filename.

Parameters:
filename - the file to play
Returns:
0 if playback completes without a digit being pressed, or -1 on error or if the channel was disconnected.
Throws:
java.io.IOException - if the connection is lost.

streamFile

public int streamFile(java.lang.String filename,
                      java.lang.String escapeDigits)
               throws java.io.IOException
Send the given file, allowing playback to be interrupted by the given digits, if any.

Remember, the file extension must not be included in the filename.

Parameters:
filename - the file to play
escapeDigits - the permitted interrupt digits
Returns:
0 if playback completes without a digit being pressed, or the ASCII value of the digit if one was pressed, or -1 on error or if the channel was disconnected.
Throws:
java.io.IOException - if the connection is lost.

streamFile

public int streamFile(java.lang.String filename,
                      java.lang.String escapeDigits,
                      long sampleOffset)
               throws java.io.IOException
Send the given file, allowing playback to be interrupted by the given digits, if any. Remember, the file extension must not be included in the filename.

Parameters:
filename - the file to play
escapeDigits - the permitted interrupt digits
sampleOffset - the audio will seek to sample offset before play starts
Returns:
0 if playback completes without a digit being pressed, or the ASCII value of the digit if one was pressed, or -1 on error or if the channel was disconnected.
Throws:
java.io.IOException - if the connection is lost.

tddMode

public int tddMode(boolean enable)
            throws java.io.IOException
Enable/Disable TDD transmission/reception on a channel.

Parameters:
enable - true to enable.
Returns:
Returns 1 if successful, or 0 if channel is not TDD-capable.
Throws:
java.io.IOException - if the connection is lost.

verbose

public int verbose(java.lang.String message,
                   java.lang.String level)
            throws java.io.IOException
Sends text to the console via verbose message system.

Parameters:
message - to send
level - is the the verbose level (1-4)
Returns:
1 always.
Throws:
java.io.IOException - if the connection is lost.

getServer

public AGIServer getServer()
Gets the AGIServer that received this connection.

Returns:
Returns the server.

setServer

public void setServer(AGIServer server)
Parameters:
server - The server to set.

getSocket

public java.net.Socket getSocket()
Returns:
Returns the socket that represents the connection to Asterisk for this call.

setSocket

public void setSocket(java.net.Socket socket)
Parameters:
socket - The socket to set.