123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
- <section id="application_writing" xmlns:xi="http://www.w3.org/2001/XInclude">
- <sectioninfo>
- <revhistory>
- <revision>
- <revnumber>$Revision$</revnumber>
- <date>$Date$</date>
- </revision>
- </revhistory>
- </sectioninfo>
-
- <title>Application Writing</title>
- <para>
- <application>ser</application> offers several
- ways to couple its functionality with applications. The coupling
- is bidirectional: <application>ser</application>
- can utilize external applications and external applications can
- utilize <application>ser</application>.
- An example of the former direction would be an external program
- determining a least-cost route for a called destination using
- a pricing table. An example of the latter case
- is a web application for server provisioning.
- Such an application may want to send instant
- messages, query all current user's locations and monitor server
- health. An existing web interface to <application>ser</application>,
- <application>serweb</application>, actually
- does all of it.
- </para>
- <para>
- The easiest, language-independent way of using external logic
- from <application>ser</application> is provided
- by exec module. exec module allows <application>ser</application>
- to start external programs on receipt of a request. The
- programs can execute arbitrary logic and/or affect routing of SIP
- requests. A great benefit of this programming method is it
- is language-independent. Programmers may use programming languages
- that are effective or with which they are best familiar.
- <xref linkend="usingexec"/> gives additional examples illustrating
- use of the exec module.
- </para>
- <para>
- Another method for extending <application>ser</application>
- capabilities is to write new modules in C. This method takes
- deeper understanding of <application>ser</application>
- internals but gains the highest flexibility. Modules can implement
- arbitrary brand-new commands upon which <application>ser</application>
- scripts can rely on. Guidelines on module programming can be
- found in <application>ser</application>
- programmer's handbook available from iptel.org website.
- </para>
- <para>
- To address needs of applications wishing to leverage
- <application>ser</application>,
- <application>ser</application> exports
- parts of its functionality via its built-in
- "Application FIFO server". This is a simple textual
- interface that allows any external applications
- to communicate with the server. It can be used to
- send instant messages, manipulate user contacts,
- watch server health, etc. Programs written in any
- language (PHP, shell scripts, Perl, C, etc.) can
- utilize this feature. How to use it is shown in
- <xref linkend="fifoserver"/>.
- </para>
- <section id="usingexec">
- <title>Using exec Module</title>
- <para>
-
- The easiest way is to couple <application>ser</application>
- with external applications via the <emphasis>exec</emphasis>
- module. This module allows execution of logic and URI manipulation
- by external applications on request receipt. While very
- simple, many useful services can be
- implemented this way. External applications can be written in
- any programming language and do not be aware of SIP at all.
- <application>ser</application> interacts with
- the application via standard input/output and environment
- variables.
- </para>
- <para>
- For example, an external shell script
- may send an email whenever a request for a user arrives.
- </para>
- <example>
- <title>Using exec: Step 1</title>
- <programlisting>
- # send email if a request for user "jiri" arrives
- if (uri=~"^sip:jiri@") {
- exec_msg("echo 'body: call arrived'|mail -s 'call for you' jiri");
- }
- </programlisting>
- </example> <!-- step 1 -->
- <para>
- In this example, the <command>exec_msg</command>
- action starts an external shell. It passes a received SIP request
- to shell's input. In the shell, <command>mail</command> command
- is called to send a notification by e-mail.
- The script however features several simplifications:
- <orderedlist inheritnum="ignore" continuation="restarts">
- <listitem>
- <para>
- The email notification does not tell who was calling.
- </para>
- </listitem>
- <listitem>
- <para>
- The logic is not general: it only supports one well-known user (jiri).
- </para>
- </listitem>
- <listitem>
- <para>
- The logic is stateless. It will be executed on
- every retransmission.
- </para>
- </listitem>
- <listitem>
- <para>
- It is a script fragment not explaining the
- context. This particular example may be for
- example used to report on missed calls.
- </para>
- </listitem>
- </orderedlist>
- All of these simplifications are addressed step-by-step
- in the following examples.
- </para>
- <example> <!-- step 2: who called me -->
- <title>Using exec: Step 2, Who Called Me</title>
- <para>
- This example shows how to display caller's address
- in email notification. The trick is easy: process
- request received on shell program's input
- and grep From header field.
- </para>
- <programlisting>
- <xi:include href="../../examples/exec_s2.cfg" parse="text"/>
- </programlisting>
- <para>
- The following two figures show an example SIP request and
- email notification generated on its receipt.
- <screen>
- <![CDATA[
- INVITE sip:[email protected] SIP/2.0
- Via: SIP/2.0/UDP 195.37.77.100:5040
- Max-Forwards: 10
- From: "alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
- To: <sip:[email protected]>
- Call-ID: [email protected]
- CSeq: 2 INVITE
- Contact: <sip:123.20.128.35:9315>
- Content-Type: application/sdp
- Content-Length: 451
- --- SDP payload snipped ---
- ]]>
- </screen>
-
- email received:
-
- <screen>
- <![CDATA[
- Date: Thu, 12 Dec 2002 14:25:02 +0100
- From: root <[email protected]>
- To: [email protected]
- Subject: request for you
- From: "alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
- request received
- ]]>
- </screen>
- </para>
- <para>
- There is another way to learn values of request
- header fields, simpler than use of <command>grep</command>.
- <application>ser</application>
- parses header fields and passes their values in
- environment variables. Their names correspond
- to header field names prefixed with "SIP_HF_".
- <programlisting>
- # send email if a request for "jiri" arrives
- if (uri=~"^sip:jiri@") {
- exec_msg("echo request received from $SIP_HF_FROM | mail -s 'request for you' jiri");
- };
- </programlisting>
- Moreover, several other values are passed in environment
- variables. <varname>SIP_TID</varname> is a token uniquely identifying
- transaction, to which the request belongs. <varname>SIP_DID</varname>
- includes to-tag, and is empty in requests creating a dialog.
- <varname>SIP_SRCIP</varname> includes IP address, from which the
- request was sent. <varname>SIP_RURI</varname> and <varname>SIP_ORURI</varname>
- include current request-uri and original request-uri respectively,
- <varname>SIP_USER</varname> and <varname>SIP_OUSER</varname> username
- parts of these. The following listing shows environment variables
- passed to a shell script on receipt of the previous message:
- <programlisting>
- <![CDATA[
- SIP_HF_MAX_FORWARDS=10
- SIP_HF_VIA=SIP/2.0/UDP 195.37.77.100:5040
- SIP_HF_CSEQ=2 INVITE
- SIP_HF_FROM="alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
- SIP_ORUI=sip:[email protected]
- SIP_HF_CONTENT_LENGTH=451
- SIP_TID=3b6b8295db0835815847b1f35f3b29b8
- SIP_DID=
- SIP_RURI=iptel.org
- SIP_HF_TO=<sip:[email protected]>
- SIP_OUSER=jiri
- [email protected]
- SIP_SRCIP=195.37.77.100
- SIP_HF_CONTENT_TYPE=application/sdp
- SIP_HF_CONTACT=<sip:123.20.128.35:9315>
- ]]>
- </programlisting>
-
- </para>
- </example> <!-- step 2, who called me -->
- <example> <!-- step 3, make the script work for anyone -->
- <title>Using exec: step 3, Make The Script Work For Anyone</title>
- <para>
- A drawback of the previous example is it works only
- for one well-known user: request URI is matched against
- his SIP address and notification is sent to his hard-wired email
- address. In real scenarios, one would like
- to enable such a service for all users without enumerating
- their addresses in the script. The missing piece
- is translation of user's SIP name to his email address.
- This information is maintained in subscriber profiles,
- stored in MySQL by <application>ser</application>.
- To translate the username to email address, the executed script
- needs to query the MySQL database. That is what this example
- shows. First, an SQL query is constructed which looks up
- email address of user, for whom a request arrived. If the
- query does not return a valid email address, the script
- returns with an error status and <application>ser</application>
- script replies with "user does not exist". Otherwise
- an email notification is sent.
-
- <programlisting>
- <xi:include href="../../examples/exec_s3.cfg" parse="text"/>
- </programlisting>
- </para>
- </example> <!-- step 3 make the script work for anyone -->
- <example> <!-- step 4, stateful processing -->
- <title>Adding Stateful Processing</title>
- <para>
- The previously improved example still features a shortcoming.
- When a message retransmission arrives due to a network
- mistake such as lost reply, the email notification is
- executed again and again. That happens because the script
- is stateless, i.e., no track of current transactions is
- kept. The script does not know whether a request is
- a new or a retransmitted one. Transaction management may
- be introduced by use of tm module as described in
- <xref linkend="statefulua"/>. In the script,
- <command>t_newtran</command> is first
- called to absorb requests retransmission -- if they
- occur, script does not continue. Then, as in the previous
- example, an exec module action is called. Eventually,
- a reply is sent statefully.
- <note>
- <para>
- Note carefully: it is important that the stateful
- reply processing (<command>t_reply</command>)
- is used as opposed to using stateless replies
- (<command>sl_send_reply</command>).
- Otherwise, the outgoing reply would not affect
- transactional context and would not be resent on
- receipt of a request retransmission.
- </para>
- </note>
- <programlisting>
- <xi:include href="../../examples/exec_s4.cfg" parse="text"/>
- </programlisting>
-
- </para>
- </example> <!-- step 4, stateful processing -->
- <example> <!-- step 5, full exec use -->
- <title>Full Example of exec Use</title>
- <para>
- The last example iteration shows how to integrate the
- email notification on missed calls with the default
- <application>ser</application> script
- (see <xref linkend="defaultscript"/>). It generates an
- email for every call invitation to an off-line user.
- <programlisting>
- <xi:include href="../../examples/exec_s5.cfg" parse="text"/>
- </programlisting>
- </para>
-
- <para>
- Production "missed calls" services may want to
- report on calls missed for other reasons than
- being off-line too. Particularly, users may wish to be
- reported calls missed due to call cancellation,
- busy status or a downstream failure. Such missed
- calls can be easily reported to syslog or mysql
- using the acc module (see <xref linkend="missedcalls"/>).
- The other, more general way, is to return to request
- processing on receipt of a negative reply.
- (see <xref linkend="replyprocessingsection"/>). Before
- a request is forwarded, it is labeled to be
- re-processed in a <command>failure_route</command>
- on receipt of a negative reply -- this is what
- <command>t_on_failure</command> action
- is used for. It does not matter what caused the transaction
- to fail -- it may be unresponsive downstream server,
- server responding with 6xx, or server sending a 487
- reply, because an INVITE was canceled. When any such
- circumstances occur (i.e., transaction does not complete
- with a 2xx status code), <command>failure_route</command>
- is entered.
- </para>
- <para>
- The following <application>ser</application>
- script reports missed calls in all possible cases.
- It reports them when a user is off-line as well as when
- a user is on-line, but INVITE transaction does not complete
- successfully.
- <programlisting>
- <xi:include href="../../examples/exec_s5b.cfg" parse="text"/>
- </programlisting>
- </para>
-
- </example> <!-- step 5, full exec use -->
- </section> <!-- using exec -->
- <section id="fifoserver">
- <title>Application FIFO Server</title>
- <para>
- Application FIFO server is a very powerful method to program
- SIP services. The most valuable benefit
- is it works with SIP-unaware applications
- written in any programming language. Textual nature of the
- FIFO interface allows for easy integration with a lot of
- existing programs. Today, <application>ser</application>'s
- complementary web-interface, <application>serweb</application>,
- written in PHP, leverages the FIFO interface when displaying
- and changing user location records stored in server's memory.
- It uses this interface to send instant messages too, without
- any knowledge of underlying <acronym>SIP</acronym> stack.
- Another application relying on the FIFO interface is
- <application>serctl</application>, <application>ser</application>
- management utility. The command-line utility can browse
- server's in-memory user-location database, display
- running processes and operational statistics.
- </para>
- <para>
- The way the FIFO server works is similar to how
- <filename>/proc</filename> filesystem works
- on some operating systems. It provides a human-readable way
- to access <application>ser</application>'s
- internals. Applications dump their requests into the FIFO
- server and receive a status report when request processing
- completes. <application>ser</application>
- exports a lot of its functionality located in both the
- core and external modules through the FIFO server.
- </para>
- <para>
- FIFO requests are formed easily. They begin with a command
- enclosed in colons and followed by name of file or pipe (relative
- to <filename>/tmp/</filename> path), to which
- a reply should be printed. The first request line may be
- followed by additional lines with command-specific
- parameters. For example, the <command>t_uac_dlg</command>
- FIFO command for initiating a transaction allows
- to pass additional header fields and message body to
- a newly created transaction. Each request is terminated by
- an empty line. Whole requests must be sent by applications
- atomically in a single batch to avoid mixing with
- requests from other applications. Requests are sent to
- pipe at which <application>ser</application>
- listens (filename configured by the <varname>fifo</varname> config
- file option).
- </para>
- <para>
- An easy way to use the FIFO interface is via the
- <application>serctl</application>
- command-line tool. When called along with "fifo",
- FIFO command name, and optional parameters, the tool
- generates a FIFO request and prints request result.
- The following example shows use of this tool with
- the <command>uptime</command> and
- <command>which</command> commands.
- <command>uptime</command> returns
- server's running time, <command>which</command>
- returns list of available FIFO commands. Note that only
- the built-in FIFO command set is displayed as no modules
- were loaded in this example.
- <example>
- <title>Use of <application>serctl</application>
- to Access FIFO Server</title>
- <programlisting>
- [jiri@cat test]$ serctl fifo uptime
- Now: Fri Dec 6 17:56:10 2002
- Up Since: Fri Dec 6 17:56:07 2002
- Up time: 3 [sec]
- [jiri@cat test]$ serctl fifo which
- ps
- which
- version
- uptime
- print
- </programlisting>
- </example>
- The request which the <application>serctl</application>
- command-line tool sent to FIFO server looked like this:
- <example>
- <title><command>uptime</command> FIFO Request</title>
- <programlisting>
- :uptime:ser_receiver_1114
- </programlisting>
- </example>
- This request contains no parameters and consists only of
- command name enclosed in colons and name of file, to which
- a reply should be printed. FIFO replies consist of a status
- line followed by optional parameters. The status line consists,
- similarly to <acronym>SIP</acronym> reply status, of
- a three-digit status code and a reason phrase. Status codes
- with leading digit 2 (200..299) are considered positive,
- any other values indicate an error. For example, FIFO server
- returns "500" if execution of a non-existing FIFO command is
- requested.
- <example>
- <title>FIFO Errors</title>
- <programlisting>
- [jiri@cat sip_router]$ serctl fifo foobar
- 500 command 'foobar' not available
- </programlisting>
- </example>
- <example>
- <title>Showing User Contacts Using serctl</title>
- <para>
- Another example of use of FIFO is accessing server's
- in-memory user location database. That's a very powerful
- feature: web applications and other tools can use it
- to gain users access to the database. They can add new
- contacts (like permanent gateway destinations), remove
- and review users' whereabouts. The example here utilizes
- FIFO command <command>ul_show_contact</command> to
- retrieve current whereabouts of user "jiri".
- <programlisting>
- <![CDATA[
- [jiri@fox ser]$ serctl fifo ul_show_contact location jiri
- <sip:195.37.78.160:14519>;q=0.00;expires=1012
- ]]>
- </programlisting>
- </para>
- </example>
- </para>
- <para>
- The user location example demonstrates an essential feature
- of the FIFO server: extensibility. It is able to export new
- commands implemented in new modules.
- Currently, usrloc module exports FIFO
- commands for maintaining in-memory user location
- database and tm module exports FIFO commands for
- management of SIP transactions. See the
- example in
- <filename>examples/web_im/send_im.php</filename>
- for how to initiate a SIP transaction
- (instant message)
- from a PHP script via the FIFO server. This example
- uses FIFO command
- <command>t_uac_dlg</command>. The command
- is followed by parameters: header fields and
- message body. The same FIFO command can be used from
- other environments to send instant messages too. The
- following example shows how to send instant messages
- from a shell script.
- <example>
- <title>Sending IM From Shell Script</title>
- <programlisting>
- #!/bin/sh
- #
- # call this script to send an instant message; script parameters
- # will be displayed in message body
- #
- # parameters mean: message type, request-URI, outbound server is
- # left blank ("."), required header fields From and To follow,
- # then optional header fields terminated by dot and optional
- # dot-terminated body
- cat > /tmp/ser_fifo <<EOF
- :t_uac_dlg:hh
- NOTIFY
- sip:[email protected]
- .
- From: sip:[email protected]
- To: sip:[email protected]
- foo: bar_special_header
- x: y
- p_header: p_value
- Contact: <sip:[email protected]:9>
- Content-Type: text/plain; charset=UTF-8
- .
- Hello world!!!! $@
- .
- EOF
- </programlisting>
- </example>
- </para>
- <example>
- <title>Manipulation of User Contacts</title>
- <para>
- The following example shows use of FIFO server to change
- user's contacts. This may be very practical, if for example
- a user wishes to set up his cell phone number as his temporary
- contact. The cell phone, which is behind a PSTN gateway, cannot
- register automatically using SIP. The user needs to set
- forwarding manually through some convenient web interface.
- The web interface needs to have the ability to upload new user's
- contacts to <application>ser</application>.
- This is what the <command>ul_add</command> FIFO
- command is good for. Parameterized by user's name, table name,
- expiration time and weight, it allows external applications to
- introduce new contacts to server's in-memory user location table.
- </para>
- <para>
- The example is borrowed from <application>serweb</application>,
- <application>ser</application>'s web
- PHP-written interface.
- It consists of a short "stub" function which carries out
- all mechanics of FIFO communication and of forming the FIFO
- request.
- </para>
- <programlisting>
- <![CDATA[
- /* construct and send a FIFO command; the command parameters $sip_address,
- $expires are PHP variables originating from an HTML form
- */
- $fifo_cmd=":ul_add:".$config->reply_fifo_filename."\n".
- $config->ul_table."\n". //table
- $user_id."\n". //username
- $sip_address."\n". //contact
- $expires."\n". //expires
- $config->ul_priority."\n\n"; //priority
- $message=write2fifo($fifo_cmd, $errors, $status);
- /* .......... snip .................. */
- /* this is the stub function for communicating with FIFO server.
- it dumps a request to FIFO server, opens a reply FIFO and
- reads server's reply from it
- */
- function write2fifo($fifo_cmd, &$errors, &$status){
- global $config;
- /* open fifo now */
- $fifo_handle=fopen( $config->fifo_server, "w" );
- if (!$fifo_handle) {
- $errors[]="sorry -- cannot open fifo"; return;
- }
-
- /* create fifo for replies */
- @system("mkfifo -m 666 ".$config->reply_fifo_path );
- /* add command separator */
- $fifo_cmd=$fifo_cmd."\n";
-
- /* write fifo command */
- if (fwrite( $fifo_handle, $fifo_cmd)==-1) {
- @unlink($config->reply_fifo_path);
- @fclose($fifo_handle);
- $errors[]="sorry -- fifo writing error"; return;
- }
- @fclose($fifo_handle);
-
- /* read output now */
- @$fp = fopen( $config->reply_fifo_path, "r");
- if (!$fp) {
- @unlink($config->reply_fifo_path);
- $errors[]="sorry -- fifo reading error"; return;
- }
- $status=fgetS($fp,256);
- if (!$status) {
- @unlink($config->reply_fifo_path);
- $errors[]="sorry -- fifo reading error"; return;
- }
-
- $rd=fread($fp,8192);
- @unlink($config->reply_fifo_path);
-
- return $rd;
- }
- ]]>
- </programlisting>
- </example>
- <para>
- See
- <xref linkend="fiforeference"/> for a complete listing
- of FIFO commands available with current
- <application>ser</application>
- distribution.
- </para>
- <section>
- <title>Advanced Example: Click-To-Dial</title>
- <para>
- A very useful SIP application is phonebook with
- "click-to-dial" feature. It allows users to keep their
- phonebooks on the web and dial by clicking on an entry.
- The great advantage is that you can use the phonebook
- alone with any phone you have. If you temporarily use
- another phone, upgrade it permanently with another make,
- or use multiple phones in parallel, your phonebook will
- stay with you on the web. You just need to click an entry
- to initiate a call. Other scenario using "click-to-dial"
- feature includes "click to be connected with our
- sales representative".
- </para>
- <para>
- There are basically two ways how to build such a feature:
- distributed and centralized. We prefer the distributed
- approach since it is very robust and light-weighted.
- The "click-to-dial" application just needs to instruct
- the calling user to call a destination and that's it.
- (That's done using "REFER" method.)
- Then, the calling user takes over whereas the initiating
- application disappears from signaling and
- is no longer involved in subsequent communication. Which
- is good because such a simple design scales well.
- </para>
- <para>
- The other design alternative is use of a B2BUA
- <footnote>
- <para>
- See <filename>
- draft-ietf-sipping-3pcc-02.txt
- </filename> for more details.
- </para>
- </footnote>
- which acts as a "middleman" involved in signaling during the
- whole session. It is complex: ringing needs to be achieved
- using a media server, it introduces session state,
- mangling of SIP payloads, complexity when QoS reservation
- is used and possibly other threats which result from
- e2e-unfriendly design. The only benefit
- is it works even for poor phones which do not support
- REFER -- which should not matter because you do not wish
- to buy such.
- </para>
- <para>
- So how does "distributed click-to-dial" application
- work? It is simple. The core piece is sending a REFER
- request to the calling party. REFER method is typically
- used for call transfer and it means "set up a call
- to someone else".
- </para>
- <para>
- There is an issue -- most phones
- don't accept unsolicited REFER. If a malicious
- user made your phone to call thirty destinations without
- your agreement, you would certainly not appreciate it.
- The workaround is that first of all the click-to-dial
- application gives you a "wrapper call". If you accept it,
- the application will send a REFER which will be considered
- by the phone as a part of approved communication and
- granted. Be aware that without cryptography,
- security is still weak. Anyone who saw an INVITE can
- generate an acceptable REFER.
- <note>
- <para>
- The wrapper INVITE may or may not be used
- in future. The Internet draft
- draft-ietf-sipping-service-examples
- mentions the click-to-dial application
- without use of the dummy INVITE. As of
- today, most telephones do need it.
- </para>
- </note>
- <example>
- <title>Call-Flow for Click-To-Dial Using REFER</title>
- <programlisting>
- CTD Caller Callee
- #1 INVITE
- ----------------->
- ...
- caller answers
- #2 200
- <-----------------
- #3 ACK
- ----------------->
- #4 REFER
- ----------------->
- #5 202
- <-----------------
- #6 BYE
- ----------------->
- #7 200
- <-----------------
- #8 INVITE
- ------------------>
- #9 180 ringing
- <------------------
- #1 click-to-dial (CTD) is started and the "wrapper call" is initiated
- INVITE caller
- From: controller
- To: caller
- SDP: on hold
- #2 calling user answes
- 200 OK
- From: controller
- To: caller
- #3 CTD acknowledges
- ACK caller
- From controller
- To: caller
- #4 CTD initiates a transfer
- REFER caller
- From: controller
- To: caller
- Refer-To: callee
- Refered-By: controller
- #5 caller confirms delivery of REFER
- 202 Accepted
- From: controller
- To: caller
- #6 CTD terminates the wrapper call -- it is no longer needed
- BYE caller
- From: controller
- To: caller
- #7 BYE is confirmed
- 200 Ok
- From: controller
- To: caller
- #8 caller initates transaction solicited through REFER
- INVITE callee
- From: caller
- To: callee
- Referred-By: controller
- #9 that's it -- it is now up to callee to answer the INVITE
- 180 ringing
- From: caller
- To: callee
- </programlisting>
- </example>
- </para>
- <para>
- Implementation of this scenario is quite
- straight-forward: you initiate INVITE, BYE and
- REFER transaction.
- Source code of the example written in Bourne shell
- is available in source distrubtion, in
- <filename>examples/ctd.sh</filename>.
- A PHP implementation exists as well as a part of
- <application>serweb</application>.
- </para>
- <example>
- <title>Running the CTD Example</title>
- <programlisting>
- [jiri@cat examples]$ ./ctd.sh
- destination unspecified -- taking default value sip:[email protected]
- caller unspecified -- taking default value sip:[email protected]
- invitation succeeded
- refer succeeded
- bye succeeded
- </programlisting>
- </example>
- </section> <!-- click-to-dial -->
- <!-- for some reason, this does not work :-(
- <example>
- <title>Initiating a SIP Transaction from PHP via FIFO</title>
- <programlisting>
- <textobject>
- <textdata fileref="../../examples/web_im/send_im.php">
- </textobject>
-
- </programlisting>
-
- </example>
- -->
- </section> <!-- FIFO server -->
- </section>
-
|