click-to-dial completed
authorJiri Kuthan <jiri@iptel.org>
Thu, 27 Feb 2003 20:29:25 +0000 (20:29 +0000)
committerJiri Kuthan <jiri@iptel.org>
Thu, 27 Feb 2003 20:29:25 +0000 (20:29 +0000)
doc/seruser/seruser.sgml
examples/ctd.sh
examples/logging.cfg [new file with mode: 0644]
modules/tm/t_lookup.c
modules/tm/uac.c

index be5b4e0..eb7bcf3 100644 (file)
@@ -19,6 +19,7 @@
 <!ENTITY execstep5 SYSTEM "../../examples/exec_s5.cfg">
 <!ENTITY execstep5b SYSTEM "../../examples/exec_s5b.cfg">
 <!ENTITY ccdiversion SYSTEM "../../examples/ccdiversion.cfg">
+<!ENTITY logging SYSTEM "../../examples/logging.cfg">
 <!ENTITY releasenotes SYSTEM "../../NEWS">
 <!ENTITY install SYSTEM "../../INSTALL">
 <!ENTITY voicemail SYSTEM "voicemail.sgml">
@@ -1957,7 +1958,7 @@ route{
            </section> <!-- exec example -->
            
            <section id="replyprocessingsection">
-               <title>Reply Processing (Forward on Unavailable)</title>
+               <title>On-Reply Processing (Forward on Unavailable)</title>
                <para>
                    Many services depend on status of messages relayed
                    downstream: <emphasis>forward on busy</emphasis> and 
@@ -1980,6 +1981,18 @@ route{
                    (status code >= 300 ) from upstream or not receiving
                    any final reply within final response period.
                </para>
+               <para>
+                   The length of the timer is governed by parameters of the
+                   tm module. <varname>fr_timer</varname> is the length of
+                   timer set for non-INVITE transactions and INVITE transactions
+                   for which no provisional response is received. If a timer
+                   hits, it indicates that a downstream server is unresponsive.
+                   <varname>fr_inv_timer</varname> governs time to wait for 
+                   a final reply for an INVITE. It is typically longer than
+                   <varname>fr_timer</varname> because final reply may take
+                   long time until callee (finds a mobile phone in a pocket and)
+                   answers the call.
+               </para>
                <para>
                    In <xref linkend="replyprocessing">, <command moreinfo="none">reply_route[1]</command>
                    is set to be entered on error using the <command moreinfo="none">t_on_negative(1)</command>
@@ -1991,7 +2004,7 @@ route{
                    is entered and a last resort destination (sip:foo@iptel.org) is tried.
                </para>
                <example id="replyprocessing">
-                   <title>Reply Processing</title>
+                   <title>On-Reply Processing</title>
                    <programlisting format="linespecific">
                        <!-- ../../examples/onr.cfg -->
                        &replyexample;
@@ -2005,7 +2018,7 @@ route{
 
     <chapter>
        <title>Server Operation</title>
-       <section>
+       <section id="operationalpractices">
            <title>Recommended Operational Practices</title>
 
            <para>
@@ -2296,23 +2309,6 @@ warning: IP extract from warning activated to be more informational
                    </para>
                </answer>
            </qandaentry>
-               <qandaentry>
-                   <question>
-                       <para>
-                           Setting Proper Log Level
-                       </para>
-                   </question>
-                   <answer>
-                       <para>
-                           If something is going wrong and you are in doubts what causes the
-                           error, increase log level. Additional log messages may help you
-                           to trace the error reason. Be careful though: <application moreinfo="none">
-                           ser</application> is very talkative in higher debugging levels.
-                           Too noisy log files are difficult to read too and server's
-                           operation slows down noticeably.
-                       </para>
-                   </answer>
-               </qandaentry>
            <qandaentry>
                <question>
                    <para>
@@ -2364,25 +2360,103 @@ warning: IP extract from warning activated to be more informational
                                </para>
                        </question>
                        <answer>
-                               <para>
-                                       <application>ser</application> by default logs
-                                       to <application>syslog</application> facility.
-                                       It is very useful to watch log messages for
-                                       abnormal behaviour. Log messages, subject to
-                                       <application>syslog</application> configuration
-                                       may be stored at different files, or even at remote
-                                       systems. A typical location of the log file is
-                                       <filename>/var/log/messages</filename>.
-                               </para>
-                               <para>
-                                       One can also use other <application>syslogd</application>
-                                       implementation. <application>metalog</application>
-                                       (<ulink url="http://http://metalog.sourceforge.net//">
-                               http://metalog.sourceforge.net/
-                                       </ulink>)
-                                       features regular expression matching that enables
-                                       to filter and group log messages.
-                               </para>
+                       <anchor id="logging">
+                       <para>
+                           <application>ser</application> by default logs
+                           to <application>syslog</application> facility.
+                           It is very useful to watch log messages for
+                           abnormal behaviour. Log messages, subject to
+                           <application>syslog</application> configuration
+                           may be stored at different files, or even at remote
+                           systems. A typical location of the log file is
+                           <filename>/var/log/messages</filename>.
+                       </para>
+                       <note>
+                           <para>
+                               One can also use other <application>syslogd</application>
+                               implementation. <application>metalog</application>
+                               (<ulink url="http://http://metalog.sourceforge.net//">
+                                   http://metalog.sourceforge.net/
+                               </ulink>)
+                               features regular expression matching that enables
+                               to filter and group log messages.
+                           </para>
+                       </note>
+                       <para>
+                           For the purpose of debugging configuration scripts, one may
+                           want to redirect log messages to console not to pollute
+                           syslog files. To do so configure <application moreinfo="none">ser</application>
+                           in the following way:
+                           <itemizedlist>
+                               <listitem>
+                                   <para>
+                                       Attach ser to console by setting <varname>fork=no</varname>.
+                                   </para>
+                               </listitem>
+                               <listitem>
+                                   <para>
+                                       Set explicitely at which address 
+                                       <application moreinfo="none">ser</application>
+                                       should be listening, e.g., <varname>listen=192.168.2.16</varname>.
+                                   </para>
+                               </listitem>
+                               <listitem>
+                                   <para>
+                                       Redirect log messages to standard error by setting
+                                       <varname>log_stderror=yes</varname>
+                                   </para>
+                               </listitem>
+                               <listitem>
+                                   <para>
+                                       Set appropriately high log level. (Be sure that you redirected logging
+                                       to standard output. Flooding system logs with many detailed messages
+                                       would make the logs difficult to read and use.) You can set the global
+                                       logging threshold value with the option <varname>debug=nr</varname>,
+                                       where the higher <varname>nr</varname> the more detailed output.
+                                       If you wish to set log level only for some script events, include
+                                       the desired log level as the first parameter of the
+                                       <command moreinfo="none">log</command> action in your script.
+                                       The messages will be then printed if <command moreinfo="none">log</command>'s
+                                       level is lower than the global threshold, i.e., the lower the more
+                                       noisy output you get.
+                                       <example>
+                                           <title>Logging Script</title>
+                                           <programlisting format="linespecific">
+&logging;
+                                           </programlisting>
+                                           <para>
+                                               The following SIP message causes then logging output as shown
+                                               bellow.
+                                           </para>
+                                           <programlisting format="linespecific">
+REGISTER sip:192.168.2.16 SIP/2.0
+Via: SIP/2.0/UDP 192.168.2.33:5060
+From: sip:113311@192.168.2.16
+To: sip:113311@192.168.2.16
+Call-ID: 00036bb9-0fd305e2-7daec266-212e5ec9@192.168.2.33
+Date: Thu, 27 Feb 2003 15:10:52 GMT
+CSeq: 101 REGISTER
+User-Agent: CSCO/4
+Contact: sip:113311@192.168.2.33:5060
+Content-Length: 0
+Expires: 600                                 
+                                           </programlisting>
+                                           <programlisting format="linespecific">
+[jiri@cat sip_router]$ ./ser -f examples/logging.cfg 
+Listening on 
+              192.168.2.16 [192.168.2.16]::5060
+Aliases: cat.iptel.org:5060 cat:5060 
+WARNING: no fork mode 
+ 0(0) INFO: udp_init: SO_RCVBUF is initially 65535
+ 0(0) INFO: udp_init: SO_RCVBUF is finally 131070
+ 0(17379) REGISTER received
+ 0(17379) request for other domain received                                    
+                                           </programlisting>
+                                       </example>
+                                   </para>
+                               </listitem>
+                           </itemizedlist>
+                       </para>
                        </answer>
                </qandaentry>
            <qandaentry>
@@ -2826,12 +2900,13 @@ MySql Password:
            </section> <!-- reliability -->
            <section>
                <title>Stateful versus Stateless Forwarding</title>
-                       <para>
-                           <application moreinfo="none">ser</application> allows both stateless
-                           and stateful request processing. This memo explains what are pros and cons of
-                           using each method. The rule of thumb is "stateless for scalability,
-                           stateful for services".
-                       </para>
+               <para>
+                   <application moreinfo="none">ser</application> allows both stateless
+                   and stateful request processing. This memo explains what are pros and cons of
+                   using each method. The rule of thumb is "stateless for scalability,
+                   stateful for services". If you are unsure which you need, stateful
+                   is a safer choice which supports more usage scenarios.
+               </para>
                        <para>
                            Stateless forwarding with the
                            <command moreinfo="none">forward(uri:host, uri:port)</command> action
@@ -2881,6 +2956,36 @@ MySql Password:
                                        action must be processed statefuly.
                                    </para>
                                </listitem>
+                       <listitem>
+                           <para>
+                               <emphasis>
+                                   Fail-over.
+                               </emphasis>
+                               If you wish to try out another destination, after a primary destination
+                               failed you need to use stateful processing. With stateless processing
+                               you never know with what status a forwarded request completed downstream
+                               because you immediately release all processing information after the 
+                               request is sent out. 
+
+                               <note>
+                                   <para>
+                                       Positive return value of stateless
+                                       <command moreinfo="none">forward</command> action only indicates that
+                                       a request was successfuly sent out, and does not gain any knowledge
+                                       about whether it was successfuly received or replied. Neither does
+                                       the return value of
+                                       the stateful <command moreinfo="none">t_relay</command> action family
+                                       gain you this knowledge. However, these actions store transactional
+                                       context with which includes original request and allows you to
+                                       take an action when a negative reply comes back or a timer strikes.
+                                       See <xref linkend="replyprocessingsection"> for an example script 
+                                       which launches another
+                                       branch if the first try fails.
+                                   </para>
+                               </note>
+
+                           </para>
+                       </listitem>
                            </itemizedlist>
                        </para>
            </section> <!-- stateful vs. stateless -->
@@ -3222,7 +3327,9 @@ if (to me):
            <title>Troubleshooting</title>
            <para>
                This section gathers practices how to deal with errors
-               known to occur frequently.
+               known to occur frequently. To understand how to watch
+               SIP messages, server logs, and in genereal how to
+               troubleshoot, read also <xref linkend="operationalpractices">. 
            </para>
            <qandaset>
                <qandaentry>
@@ -3324,6 +3431,31 @@ if (to me):
                        </para>
                    </answer>
                </qandaentry>
+               <qandaentry>
+                   <question>
+                       <para>
+                           I try to add an alias but 
+                           <command moreinfo="none">serctl</command>
+                           complains that table does not exist.
+                       </para>
+                   </question>
+                   <answer>
+                       <para>
+                           You need to run <application moreinfo="none">ser</application>
+                           and use the command
+                           <command moreinfo="none">lookup("aliases")</command>
+                           in its routing script. That's because the table 
+                           of aliases is
+                           stored in cache memory for high speed. The cache
+                           memory is only set up when the 
+                           <application moreinfo="none">ser</application>
+                           is running and configured to use it. If that is
+                           not the case, 
+                           <application moreinfo="none">serctl</application>
+                           is not able to manipulate the aliases table.
+                       </para>
+                   </answer>
+               </qandaentry>
            </qandaset>
        </section> <!-- troubleshooting -->
     </chapter> <!-- operation -->
@@ -3931,6 +4063,185 @@ function write2fifo($fifo_cmd, &$errors, &$status){
                <application moreinfo="none">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 leight-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 initating
+                   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 moreinfo="none">
+                               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.
+                   <example>
+                       <title>Call-Flow for Click-To-Dial Using REFER</title>
+
+                       <programlisting format="linespecific">
+
+        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.
+
+
+
+                   The largest amount of code
+                   is spent with getting dialog processing right.
+                   The subsequent BYE and REFER transactions need to
+                   be build using information learned from the reply
+                   to INVITE: Contact header field, To-tag and Route
+                   set. That's what the function 
+                   <function moreinfo="none">filter_fl</function>
+                   is used for. The "main" part just initiates
+                   each of the transactions, waits for its completion
+                   and proceeds to the next one until BYE is over.
+                   Source code of the example written in Bourne shell
+                   is available in source distrubtion, in 
+                   <filename moreinfo="none">examples/ctd.sh</filename>.
+                   A PHP implementation exists as well.
+               </para>
+               <example>
+                   <title>Running the CTD Example</title>
+                   <programlisting format="linespecific">
+[jiri@cat examples]$ ./ctd.sh 
+destination unspecified -- taking default value sip:23@192.168.2.16
+caller unspecified -- taking default value sip:113311@192.168.2.16
+invitation succeeded
+refer succeeded
+bye succeeded
+                   </programlisting>
+               </example>
+           </section> <!-- click-to-dial -->
 <!-- for some reason, this does not work :-(
 
                <example>
index 268f77d..5c69636 100755 (executable)
-#!/bin/sh 
+#!/bin/sh
 #
 # $Id$
+#
+# Usage: ctd.sh $FROM $TARGET
 # 
-# (currently lame) click-to-dial example using REFER
-#----------------------------------------------------
+# click-to-dial example using REFER
+#----------------------------------
+#
+# About:
+# ------
+# this script initiates a call from SIP user $FROM to SIP
+# user $TARGET; it works as follows: a dummy user invites
+# $FROM to a dummy "call on hold"; as soon as it is set up, the
+# dummy user transfers $FROM to $TARGET  (REFER transaction)
+# and terminates the dummy session established previously
+# (BYE transaction). Note: the "dummy call" is used to
+# make $FROM accept $REFER -- most of SIP phones do not
+# accept REFER if no call has not been established yet.
+#
+# Requirements: 
+# -------------
+# SER with FIFO server turned on and TM module loaded
 #
-# it half-way works using FIFO/uac; I tested it with
-# Cisco 7960 reaching Mitel 5055 and vice versa
+# Limitations: 
+# ------------
+# it only works with UACs supporting REFER; it has been tested 
+# with Cisco 7960 and Mitel 5055; Windows Messenger does not
+# support REFER; dialog parser over-simplified (see inline) but 
+# quite functional (if there is something to be fixed, it is
+# richness of SIP syntax); an awk-only rewrite would be esthetically
+# nicer, imho 
 #
-# bugs: 
-# -----
-# - to-tag in REFER not ok -- should be gained from initial 
-#   conversation (need to take fifo processing from sc) as
-#   well as the whole dialog stuff (awk could be a better hit)
-# - remove user prompt (act on receipt of a reply)
-# - bye is missing after REFER
-# - it would be cleaner to send "hold" in initial invite
-# - in my test setup, initial ACK is for some bizzar reason
-#   not forwarded statelessly by outbound proxy
-# - put this example in serdoc
-
-#URI="sip:113311@192.168.2.16"
+# History:
+# --------
+# 2003-02-27 dialog support completed (jiri)
+
+#--------------------------------
+# config: who with whom
+# address of the final destination to which we want to transfer
+# initial CSeq and CallId
+if [ -z "$2" ]; then
+       TARGET="sip:23@192.168.2.16"
+       echo "destination unspecified -- taking default value $TARGET"
+else
+       TARGET="$2"
+fi
 # address of user wishing to initiate conversation
-TARGET="sip:23@192.168.2.16"
+if [ -z "$1" ] ; then
+       URI="sip:113311@192.168.2.16"
+       echo "caller unspecified -- taking default value $URI"
+else
+       URI="$1"
+fi
+
+#---------------------------------
+# fixed config data
 FIFO="/tmp/ser_fifo"
 # address of controller
-FROM="<sip:caller@foo.bar>"
-# address of the final destination to which we want to transfer
-URI="sip:113311@192.168.2.16"
-# initial CSeq and CallId
+FROM="<sip:controller@foo.bar>"
 CSEQ="1"
 CALLIDNR=`date '+%s'`$$
-
+CALLID="${CALLIDNR}.fifouacctd"
+name="ctd_fifo_$$"
+fifo_reply="/tmp/$name"
+dlg="/tmp/$CALLID.dlg"
+FIXED_DLG=`printf "From: $FROM;tag=$CALLIDNR\nCall-ID: $CALLID\nContact: <sip:caller@!!>"`
 #----------------------------------
 
-CALLID="${CALLIDNR}.fifouacctd"
+# generate parts of FIFO-request essential to forming
+# subsequent in-dialog reuqests
+# 
+# limitations: parsing broken if <> in display names or
+# line-folding used
+filter_fl()
+{
 
-cat > $FIFO <<EOF
+awk -F ' ' '
+BEGIN { IGNORECASE=1; rri=0; line=0; ret=1;eoh=0 }
+END { # print dialog information a la RFC3261, S. 12.2.1.1
+       # calculate route set 
+       if (rri>0) { # route set not empty
+               # next-hop loose router?
+               if (match(rr[1], ";lr")) {
+                       ruri=rcontact
+                       nexthop=rr[1]
+                       rrb=1 # begin from first
+               } else { # next-hop strict router
+                       ruri=rr[1]
+                       rrb=2 # skip first
+                       rri++
+                       rr[rri]=rcontact
+                       nexthop="." # t_uac_dlg value for "use ruri"
+               }
+       } else { # no record-routing
+                       ruri=rcontact
+                       nexthop="."
+                       rrb=1 # do not enter the loop
+       }
+       # print the FIFO request header
+       print ruri
+       print nexthop
+       print to
+       for(i=rrb; i<=rri; i++ ) {
+               if (i==rrb) printf "Route: "; else printf ", "
+               printf("%s", rr[i])
+               if (i==rri) printf("\n")
+               
+       }
+       exit ret
+}
+
+# set true (0) to return value if transaction completed succesfully
+{line++; }
+line==1 && /^2[0-9][0-9] / { ret=0; next; }
+line==1 && /^[3-6][0-9][0-9] / { print; next; }
+line==1 { print "reply error"; print; next; } 
+
+# skip body
+/^$/ { eoh=1 }
+eoh==1 { next }
+
+# collect dialog state: contact, rr, to
+/^(Contact|m):/ { 
+       # contact is <>-ed; fails if < within quotes
+       if (match($0, "^(Contact|m):[^<]*<([^>]*)>", arr)) {
+               rcontact=arr[2]
+               next
+       # contact without any extras and without <>, just uri
+       } else if (match($0, "^(Contact|m):[ \t]*([^ ;\t]*)", arr)) {
+               rcontact=arr[2]
+               next
+       } else {
+               # contact parsing error
+               ret=1
+       }
+}
+
+/^Record-Route:/ {
+       # rr is always <>-ed; fails if <> within quotes
+       srch=$0
+       while (match(srch, "[^<]*<([^>]*)>", arr )) {
+               rri++
+               rr[rri]=arr[1]
+               srch=substr(srch,RLENGTH)
+       }
+}
 
+/^(To|t):/ {
+       to=$0;
+}
 
-:t_uac_dlg:qqq
+{next} # do not print uninteresting header fields
+       ' # end of awk script
+} # end of filter_fl
+
+#---------------------------
+# main
+
+# set up exit cleaner
+trap "rm -f $dlg $fifo_reply; exit" 0
+
+# set up FIFO communication
+
+if [ ! -w $FIFO ] ; then # can I write to FIFO server?
+       echo "Error opening ser's FIFO $FIFO"
+       exit 1
+fi
+mkfifo $fifo_reply # create a reply FIFO
+if [ $? -ne 0 ] ; then
+       echo "error opening reply fifo $fifo_reply"
+       exit 1
+fi
+chmod a+w $fifo_reply
+# start reader now so that it is ready for replies
+# immediately after a request is out
+cat < $fifo_reply | filter_fl > $dlg  &
+fifo_job="$!"
+
+# initiate dummy INVITE with pre-3261 "on-hold"
+# (note the dots -- they mean in order of appearance:
+# outbound uri, end of headers, end of body; eventualy
+# the FIFO request must be terminated with an empty line)
+cat > $FIFO <<EOF
+
+:t_uac_dlg:$name
 INVITE 
 $URI
 .
-From: $FROM;tag=$CALLIDNR
+$FIXED_DLG
 To: <$URI>
-Call-ID: $CALLID
 CSeq: $CSEQ INVITE
-Contact: <sip:caller@!!>
 Content-Type: application/sdp
 .
 v=0
-o=jku2 0 0 IN IP4 213.20.128.35
+o=click-to-dial 0 0 IN IP4 0.0.0.0
 s=session
-c=IN IP4 213.20.128.35
+c=IN IP4 0.0.0.0
 b=CT:1000
 t=0 0
-m=audio 54742 RTP/AVP 97 111 112 6 0
-a=rtpmap:97 red/8000
-a=rtpmap:111 SIREN/16000
-a=fmtp:111 bitrate=16000
-a=rtpmap:112 G7221/16000
-a=fmtp:112 bitrate=24000
-a=rtpmap:6 DVI4/16000
+m=audio 9 RTP/AVP 0
 a=rtpmap:0 PCMU/8000
 .
+
 EOF
 
-read -p "press any key to initiate transfer: "
+# wait for reply 
+wait $fifo_job # returns completion status of filter_fl
+if [ "$?" -ne "0" ] ; then
+       echo "invitation failed"
+       exit 1
+fi
+
+echo "invitation succeeded"
 
+# proceed to REFER now
+if [ \! -r $dlg ] ; then
+       echo "dialog broken"
+       exit 1
+fi
 CSEQ=`expr $CSEQ + 1`
 
-cat > $FIFO <<EOF
+# start reader now so that it is ready for replies
+# immediately after a request is out
+cat < $fifo_reply | filter_fl > /dev/null  &
+fifo_job="$!"
 
+# dump the REFER request to FIFO server 
+cat > $FIFO <<EOF
 
-:t_uac_dlg:qqq
+:t_uac_dlg:$name
 REFER
-$URI
-.
-From: $FROM;tag=$CALLIDNR
-To: <$URI>
-Call-ID: $CALLID
+`cat $dlg`
+$FIXED_DLG
 CSeq: $CSEQ REFER
-Contact: <sip:caller@!!>
 Referred-By: $FROM
 Refer-To: $TARGET
 .
 .
+
+EOF
+
+# report REFER status
+wait $fifo_job
+ret="$?"
+
+if [ "$ret" -ne "0" ] ; then
+       echo "refer failed"
+       exit 1
+fi
+
+echo "refer succeeded"
+
+# well, URI is trying to call TARGET but still maintains the
+# dummy call we established with previous INVITE transaction:
+# tear it down
+
+
+# dump the BYE request to FIFO server 
+CSEQ=`expr $CSEQ + 1`
+cat < $fifo_reply | filter_fl > /dev/null  &
+fifo_job="$!"
+cat > $FIFO <<EOF
+
+:t_uac_dlg:$name
+BYE
+`cat $dlg`
+$FIXED_DLG
+CSeq: $CSEQ BYE
+.
+.
+
 EOF
+
+# report BYE status
+wait $fifo_job
+ret="$?"
+
+if [ "$ret" -ne "0" ] ; then
+       echo "bye failed"
+       exit 1
+fi
+echo "bye succeeded"
diff --git a/examples/logging.cfg b/examples/logging.cfg
new file mode 100644 (file)
index 0000000..3011b34
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# $Id$
+#
+# logging example
+#
+
+# ------------------ module loading ----------------------------------
+
+fork=no
+listen=192.168.2.16
+log_stderror=yes
+debug=3
+
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+       # for testing purposes, simply okay all REGISTERs
+       if (method=="REGISTER") {
+               log(1, "REGISTER received\n");
+       } else {
+               log(1, "non-REGISTER received\n");
+       };
+       if (uri=~"sip:.*[@:]iptel.org") {
+               log(1, "request for iptel.org received\n");
+       } else {
+               log(1, "request for other domain received\n");
+       };
+}
index c464cd7..9bcd040 100644 (file)
@@ -51,6 +51,7 @@
  *
  * History:
  * ----------
+ * 2003-02-27  3261 ACK/200 consumption bug removed (jiri)
  * 2003-01-28  scratchpad removed (jiri)
  * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
  * 2003-01-23  options for disabling r-uri matching introduced (jiri)
index 3bb3eae..e1b0703 100644 (file)
  *
  * History:
  * --------
+ * 2003-02-27 FIFO/UAC now dumps reply -- good for CTD (jiri)
+ * 2003-02-13  t_uac, t _uac_dlg, gethfblock, uri2proxy changed to use 
+ *              proto & rb->dst (andrei)
  * 2003-01-29  scratchpad removed (jiri)
  * 2003-01-27  fifo:t_uac_dlg completed (jiri)
  * 2003-01-23  t_uac_dlg now uses get_out_socket (jiri)
- * 2003-02-13  t_uac, t _uac_dlg, gethfblock, uri2proxy changed to use 
- *              proto & rb->dst (andrei)
  */
 
 
@@ -595,7 +596,7 @@ done:
 }
 
 
-static void fifo_callback( struct cell *t, struct sip_msg *msg,
+static void fifo_callback( struct cell *t, struct sip_msg *reply,
        int code, void *param)
 {
 
@@ -609,14 +610,20 @@ static void fifo_callback( struct cell *t, struct sip_msg *msg,
        }
 
        filename=(char *)(t->cbp);
-       get_reply_status(&text,msg,code);
-       if (text.s==0) {
-               LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
-               fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n");
-               return;
+       if (reply==FAKED_REPLY) {
+               get_reply_status(&text,reply,code);
+               if (text.s==0) {
+                       LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
+                       fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n");
+                       return;
+               }
+               fifo_reply(filename, "%.*s", text.len, text.s );
+               pkg_free(text.s);
+       } else {
+               text.s=reply->first_line.u.reply.status.s;
+               text.len=reply->len-(reply->first_line.u.reply.status.s-reply->buf);
+               fifo_reply(filename, "%.*s", text.len, text.s );
        }
-       fifo_reply(filename, "%.*s", text.len, text.s );
-       pkg_free(text.s);
        DBG("DEBUG: fifo_callback sucesssfuly completed\n");
 }