Переглянути джерело

Merge '/examples' of kamailio svn into sip-router/examples

* '/examples' of kamailio svn:
  - renaming: openser -> kamailio
  - doubled $ sign for the env variables, otherwise they would be considered openser PVs
  - fix extra acc mysql example table
  - fix several errors in example configuration
  set proper SVN properties
  - send Message and click-to-dial scripts updated to current IM fifo syntax
  - fix for handling \r\n
  - ctd.sh version for 1.2.0+
  - added sample config to do accounting to MySQL based on default config file
  - examples updated
  - config scripts updated to reflect latest changes (mainly FIFO related)
  - 'break' replaced with 'return' in default config and example files
  Initial revision
Jan Janak 16 роки тому
батько
коміт
9bd59c5647

+ 242 - 0
examples/kamailio/acc-mysql.cfg

@@ -0,0 +1,242 @@
+# $Id$
+#
+# Sample config for MySQL accouting with Kamailio 1.2.0
+#
+# - mysql module must be compiled and installed
+#
+# - new columns have to be added since by default only few are recorded
+# - here are full SQL statements to create acc and missed_calls tables
+#
+# CREATE TABLE `acc` (
+#   `id` int(10) unsigned NOT NULL auto_increment,
+#   `method` varchar(16) NOT NULL default '',
+#   `from_tag` varchar(64) NOT NULL default '',
+#   `to_tag` varchar(64) NOT NULL default '',
+#   `callid` varchar(128) NOT NULL default '',
+#   `sip_code` char(3) NOT NULL default '',
+#   `sip_reason` varchar(32) NOT NULL default '',
+#   `time` datetime NOT NULL default '0000-00-00 00:00:00',
+#   `src_ip` varchar(64) NOT NULL default '',
+#   `dst_user` varchar(64) NOT NULL default '',
+#   `dst_domain` varchar(128) NOT NULL default '',
+#   `src_user` varchar(64) NOT NULL default '',
+#   `src_domain` varchar(128) NOT NULL default '',
+#   INDEX acc_callid (`callid`),
+#   PRIMARY KEY  (`id`)
+# );
+#
+# CREATE TABLE `missed_calls` (
+#   `id` int(10) unsigned NOT NULL auto_increment,
+#   `method` varchar(16) NOT NULL default '',
+#   `from_tag` varchar(64) NOT NULL default '',
+#   `to_tag` varchar(64) NOT NULL default '',
+#   `callid` varchar(128) NOT NULL default '',
+#   `sip_code` char(3) NOT NULL default '',
+#   `sip_reason` varchar(32) NOT NULL default '',
+#   `time` datetime NOT NULL default '0000-00-00 00:00:00',
+#   `src_ip` varchar(64) NOT NULL default '',
+#   `dst_user` varchar(64) NOT NULL default '',
+#   `dst_domain` varchar(128) NOT NULL default '',
+#   `src_user` varchar(64) NOT NULL default '',
+#   `src_domain` varchar(128) NOT NULL default '',
+#   INDEX acc_callid (`callid`),
+#   PRIMARY KEY  (`id`)
+# );
+#
+#
+
+# ----------- global configuration parameters ------------------------
+
+debug=3            # debug level (cmd line: -dddddddddd)
+fork=yes
+log_stderror=no    # (cmd line: -E)
+
+/* Uncomment these lines to enter debugging mode 
+fork=no
+log_stderror=yes
+*/
+
+check_via=no	# (cmd. line: -v)
+dns=no          # (cmd. line: -r)
+rev_dns=no      # (cmd. line: -R)
+port=5060
+children=4
+
+#
+# uncomment the following lines for TLS support
+#disable_tls = 0
+#listen = tls:your_IP:5061
+#tls_verify_server = 1
+#tls_verify_client = 1
+#tls_require_client_certificate = 0
+#tls_method = TLSv1
+#tls_certificate = "/usr/local/etc/kamailio/tls/user/user-cert.pem"
+#tls_private_key = "/usr/local/etc/kamailio/tls/user/user-privkey.pem"
+#tls_ca_list = "/usr/local/etc/kamailio/tls/user/user-calist.pem"
+
+# ------------------ module loading ----------------------------------
+
+# set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+# Uncomment this if you want to use SQL database
+# - MySQL loaded for accounting as well
+loadmodule "db_mysql.so"
+
+loadmodule "sl.so"
+loadmodule "tm.so"
+loadmodule "rr.so"
+loadmodule "maxfwd.so"
+loadmodule "usrloc.so"
+loadmodule "registrar.so"
+loadmodule "textops.so"
+loadmodule "acc.so"
+loadmodule "mi_fifo.so"
+
+# Uncomment this if you want digest authentication
+# db_mysql.so must be loaded !
+#loadmodule "auth.so"
+#loadmodule "auth_db.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- mi_fifo params --
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+# -- usrloc params --
+
+#modparam("usrloc", "db_mode",   0)
+
+# Uncomment this if you want to use SQL database 
+# for persistent storage and comment the previous line
+modparam("usrloc", "db_mode", 2)
+
+# -- auth params --
+# Uncomment if you are using auth module
+#
+#modparam("auth_db", "calculate_ha1", yes)
+#
+# If you set "calculate_ha1" parameter to yes (which true in this config), 
+# uncomment also the following parameter)
+#
+#modparam("auth_db", "password_column", "password")
+
+# -- rr params --
+# add value to ;lr param to make some broken UAs happy
+modparam("rr", "enable_full_lr", 1)
+
+# -- acc params --
+modparam("acc", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+# flag to record to db
+modparam("acc", "db_flag", 1)
+modparam("acc", "db_missed_flag", 2)
+# flag to log to syslog
+modparam("acc", "log_flag", 1)
+modparam("acc", "log_missed_flag", 2)
+# use extra accounting to record caller and callee username/domain
+# - take them from From URI and R-URI
+modparam("acc", "log_extra", "src_user=$fU;src_domain=$fd;dst_user=$rU;dst_domain=$rd")
+modparam("acc", "db_extra", "src_user=$fU;src_domain=$fd;dst_user=$rU;dst_domain=$rd")
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	# initial sanity checks -- messages with
+	# max_forwards==0, or excessively long requests
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	};
+
+	if (msg:len >=  2048 ) {
+		sl_send_reply("513", "Message too big");
+		exit;
+	};
+
+	# we record-route all messages -- to make sure that
+	# subsequent messages will go through our proxy; that's
+	# particularly good if upstream and downstream entities
+	# use different transport protocol
+	if (!is_method("REGISTER"))
+		record_route();
+
+	# subsequent messages withing a dialog should take the
+	# path determined by record-routing
+	if (loose_route()) {
+		# mark routing logic in request
+		append_hf("P-hint: rr-enforced\r\n");
+		if(is_method("BYE")) {
+			# account BYE for STOP record
+			setflag(1);
+		}
+		route(1);
+	};
+
+	# account all calls
+	if(is_method("INVITE")) {
+		# set accounting on for INVITE (success or missed call)
+		setflag(1);
+		setflag(2);
+	}
+
+	if (!uri==myself) {
+		# mark routing logic in request
+		append_hf("P-hint: outbound\r\n"); 
+		# if you have some interdomain connections via TLS
+		#if(uri=~"@tls_domain1.net") {
+		#	t_relay("tls:domain1.net");
+		#	exit;
+		#} else if(uri=~"@tls_domain2.net") {
+		#	t_relay("tls:domain2.net");
+		#	exit;
+		#}
+		route(1);
+	};
+
+	# if the request is for other domain use UsrLoc
+	# (in case, it does not work, use the following command
+	# with proper names and addresses in it)
+	if (uri==myself) {
+
+		if (is_method("REGISTER")) {
+
+			# Uncomment this if you want to use digest authentication
+			#if (!www_authorize("kamailio.org", "subscriber")) {
+			#	www_challenge("kamailio.org", "0");
+			#	exit;
+			#};
+
+			save("location");
+			exit;
+		};
+
+		if (!uri==myself) {
+			append_hf("P-hint: outbound alias\r\n"); 
+			route(1);
+		};
+
+		# native SIP destinations are handled using our USRLOC DB
+		if (!lookup("location")) {
+			sl_send_reply("404", "Not Found");
+			exit;
+		};
+		append_hf("P-hint: usrloc applied\r\n"); 
+	};
+
+	route(1);
+}
+
+
+route[1] {
+	# send it out now; use stateful forwarding as it works reliably
+	# even for UDP2TCP
+	if (!t_relay()) {
+		sl_reply_error();
+	};
+	exit;
+}
+

+ 71 - 0
examples/kamailio/acc.cfg

@@ -0,0 +1,71 @@
+#
+# $Id$
+#
+# example: accounting calls to nummerical destinations
+#
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+loadmodule "tm.so"
+loadmodule "acc.so"
+loadmodule "sl.so"
+loadmodule "maxfwd.so"
+loadmodule "rr.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- acc params --
+# set the reporting log level
+modparam("acc", "log_level", 1)
+# number of flag, which will be used for accounting; if a message is
+# labeled with this flag, its completion status will be reported
+modparam("acc", "log_flag", 1 )
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	/* ********* ROUTINE CHECKS  ********************************** */
+
+	# filter too old messages
+	if (!mf_process_maxfwd_header("10")) {
+		log("LOG: Too many hops\n");
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	};
+	if (msg:len >=  2048 ) {
+		sl_send_reply("513", "Message too big");
+		exit;
+	};
+
+    #  Process record-routing
+    if (loose_route()) { 
+		# label BYEs for accounting
+		if (method=="BYE") 
+			setflag(1);
+		t_relay();
+		exit;
+	};
+
+
+	# labeled all transaction for accounting
+	setflag(1);
+
+	# record-route INVITES to make sure BYEs will visit our server too
+	if (method=="INVITE") record_route();
+
+	# forward the request statefuly now; (we need *stateful* forwarding,
+	# because the stateful mode correlates requests with replies and
+	# drops retranmissions; otherwise, we would have to report on
+	# every single message received)
+	if (!t_relay()) {
+		sl_reply_error(); 
+		exit; 
+	};
+
+}

+ 224 - 0
examples/kamailio/ctd.sh

@@ -0,0 +1,224 @@
+#!/bin/sh
+#
+# $Id$
+#
+# Usage: ctd.sh $FROM $TARGET
+# 
+# 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
+#
+# Limitations: 
+# ------------
+# it only works with UAs supporting REFER; it has been tested 
+# with Cisco 7960, Mitel 5055, Grandstream and Pingtel; Windows 
+# Messenger does not support REFER. Never tested on solaris. 
+# Some cisco 7960 images don't work (in particular, POS30202
+# doesnt, POS3-03-8-21 does)
+#
+# History:
+# --------
+# 2003-03-01 bug_fix: route set reversed
+# 2003-02-27 dialog support completed (jiri)
+# 2003-04-28 dialog info precomputed in SER (jiri)
+# 2007-04-06 updated for Kamailio 1.2.0+ (daniel)
+
+#--------------------------------
+# 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:[email protected]"
+	echo "destination unspecified -- taking default value $TARGET"
+else
+	TARGET="$2"
+fi
+# address of user wishing to initiate conversation
+if [ -z "$1" ] ; then
+	URI="sip:[email protected]"
+	echo "caller unspecified -- taking default value $URI"
+else
+	URI="$1"
+fi
+
+#---------------------------------
+# fixed config data
+FIFO="/tmp/kamailio_fifo"
+# address of controller
+FROM="<sip:[email protected]>"
+CSEQ="1"
+CALLIDNR=`date '+%s'`$$
+CALLID="${CALLIDNR}.fifouacctd"
+name="ctd_fifo_$$"
+fifo_reply="/tmp/$name"
+dlg="/tmp/$CALLID.dlg"
+FIXED_DLG="From: $FROM;tag=$CALLIDNR\r\nCall-ID: $CALLID\r\nContact: <sip:caller@!!>\r\n"
+#----------------------------------
+
+# 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()
+{
+
+awk -F ' ' '
+BEGIN { IGNORECASE=1; line=0; eoh=0;ret=1 }
+END { exit ret; }
+
+{line++; }
+
+# line 2: status code
+line==2 && /^2[0-9][0-9] / { ret=0;next; }
+line==2 && /^[3-6][0-9][0-9] / { print; print $0 > "/dev/stderr"; next; }
+line==2 { print "reply error"; print; next; } 
+
+# skip body
+/^$/ { eoh=1 }
+eoh==1 { next }
+
+# uri and outbound uri at line 2,3: copy and paste
+line==3 { print $0; next; }
+line==4 { print $0; print "."; printf("\""); next; }
+# line 5: Route; empty if ".", copy and paste otherwise
+line==5 && /^\.$/ { next; }
+# if non-empty, copy and paste it
+line==5 { printf("%s\n", $0); next; }
+# filter out to header field for use in next requests
+/^(To|t):/ { printf("%s\n", $0); next; }
+# anything else will be ignored
+{next} 
+	' # end of awk script
+} # end of filter_fl
+
+#---------------------------
+# main
+
+# set up exit cleaner
+trap "rm -f $dlg $fifo_reply; exit 1" 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 <<EOF
+cat > $FIFO <<EOF
+:t_uac_dlg:$name
+INVITE 
+$URI
+.
+.
+"`printf "${FIXED_DLG}To: <$URI>\r\nCSeq: $CSEQ INVITE\r\nContent-Type: application/sdp\r\n"`
+"
+"`printf "v=0\r\no=click-to-dial 0 0 IN IP4 0.0.0.0\r\ns=session\r\nc=IN IP4 0.0.0.0\r\nb=CT:1000\r\nt=0 0\r\nm=audio 9 RTP/AVP 8 0\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:0 PCMU/8000\r\n"`
+"
+
+EOF
+#exit
+
+# 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`
+
+# 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:$name
+REFER
+`cat $dlg; printf "${FIXED_DLG}CSeq: $CSEQ REFER\r\nReferred-By: $FROM\r\nRefer-To: $TARGET\r\n"`
+"
+
+EOF
+
+# report REFER status
+wait $fifo_job
+ref_ret="$?"
+
+if [ "$ref_ret" -ne "0" ] ; then
+	echo "refer failed"
+else
+	echo "refer succeeded"
+fi
+
+
+# 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; printf "${FIXED_DLG}CSeq: $CSEQ BYE\r\n"`
+"
+
+EOF
+
+# report BYE status
+wait $fifo_job
+ret="$?"
+
+if [ "$ret" -ne "0" ] ; then
+	echo "bye failed"
+	exit 1
+fi
+echo "bye succeeded"
+
+# clean-up
+trap 0
+rm -f $dlg $fifo_reply
+exit $ref_ret

+ 30 - 0
examples/kamailio/exec_s3.cfg

@@ -0,0 +1,30 @@
+#
+# $Id$
+#
+# email notification to email address from mysql database
+#
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+loadmodule "exec.so"
+loadmodule "sl.so"
+
+# send email if a request arrives
+route[0] {
+     if (!exec_msg('
+	QUERY="select email_address from subscriber 
+		where user=\"$$SIP_OUSER\"";
+	EMAIL=`mysql  -Bsuser -pheslo -e "$$QUERY" kamailio`;
+	if [ -z "$$EMAIL" ] ; then exit 1; fi ;
+	echo "SIP request received from $$SIP_HF_FROM for $$SIP_OUSER" |
+	mail -s "request for you" $$EMAIL ')) {
+		# exec returned error ... user does not exist
+		sl_send_reply("404", "User does not exist");
+	} else {
+		sl_send_reply("600", "No messages for this user");
+	};
+		
+}

+ 41 - 0
examples/kamailio/exec_s4.cfg

@@ -0,0 +1,41 @@
+#
+# $Id$
+#
+# email notification to email address from mysql database
+#
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+
+loadmodule "exec.so"
+loadmodule "sl.so"
+loadmodule "tm.so"
+
+# send email if a request arrives; process statefully
+# to avoid multiple execution on request retransmissions
+route[0] {
+	# stop script processing if transaction exists
+	if ( !t_newtran()) {
+		sl_reply_error();
+		return;
+	};
+
+  	if (!exec_msg('
+		QUERY="select email_address from subscriber 
+			where user=\"$$SIP_OUSER\"";
+		EMAIL=`mysql  -Bsuser -pheslo -e "$$QUERY" ser`;
+		if [ -z "$EMAIL" ] ; then exit 1; fi ;
+		echo "SIP request received from $$SIP_HF_FROM for $$SIP_OUSER" |
+		mail -s "request for you" $$EMAIL ')) 
+	{
+		# exec returned error ... user does not exist
+		# send a stateful reply
+		t_reply("404", "User does not exist");
+	} else {
+		t_reply("600", "No messages for this user");
+	};
+		
+}

+ 68 - 0
examples/kamailio/exec_s5.cfg

@@ -0,0 +1,68 @@
+#
+# $Id$
+#
+# simple quick-start config script
+#
+
+# ----------- global configuration parameters ------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+
+loadmodule "sl.so"
+loadmodule "tm.so"
+loadmodule "usrloc.so"
+loadmodule "registrar.so"
+loadmodule "exec.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+route{
+	# uri for my domain ?
+	if (uri==myself) {
+
+		if (method=="REGISTER") {
+			save("location");
+			return;
+		};
+
+		# native SIP destinations are handled using our USRLOC DB
+		if (!lookup("location")) {
+			# proceed to email notification
+			if (method=="INVITE") route(1)
+			else sl_send_reply("404", "Not Found");
+			exit;
+		};
+	};
+	# user found, forward to his current uri now
+	if (!t_relay()) {
+		sl_reply_error();
+	};
+}
+
+/* handling of missed calls */
+route[1] {
+	# don't continue if it is a retransmission
+	if ( !t_newtran()) {
+		sl_reply_error();
+		exit;
+	};
+	# external script: lookup user, if user exists, send 
+	# an email notification to him
+    if (!exec_msg('
+		QUERY="select email_address from subscriber 
+			where user=\"$$SIP_OUSER\"";
+		EMAIL=`mysql  -Bsuser -pheslo -e "$$QUERY" ser`;
+		if [ -z "$$EMAIL" ] ; then exit 1; fi ;
+		echo "SIP request received from $$SIP_HF_FROM for $$SIP_OUSER" |
+		mail -s "request for you" $$EMAIL ')) 
+	{
+		# exec returned error ... user does not exist
+		# send a stateful reply
+		t_reply("404", "User does not exist");
+	} else {
+		t_reply("600", "No messages for this user");
+	};
+	exit;
+}

+ 103 - 0
examples/kamailio/flag_reply.cfg

@@ -0,0 +1,103 @@
+#
+# $Id$
+#
+# simple quick-start config script
+#
+
+# ----------- global configuration parameters ------------------------
+
+debug=3         # debug level (cmd line: -dddddddddd)
+fork=yes
+log_stderror=no	# (cmd line: -E)
+
+fork=no
+log_stderror=yes
+
+check_via=no	# (cmd. line: -v)
+dns=no           # (cmd. line: -r)
+rev_dns=no      # (cmd. line: -R)
+children=4
+
+port=5060
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+
+# Uncomment this if you want to use SQL database
+#loadmodule "db_mysql.so"
+
+loadmodule "sl.so"
+loadmodule "tm.so"
+loadmodule "rr.so"
+loadmodule "maxfwd.so"
+loadmodule "usrloc.so"
+loadmodule "registrar.so"
+loadmodule "textops.so"
+loadmodule "mi_fifo.so"
+
+# Uncomment this if you want digest authentication
+# mysql.so must be loaded !
+#loadmodule "auth.so"
+#loadmodule "auth_db.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- mi_fifo params --
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+# -- usrloc params --
+
+modparam("usrloc", "db_mode",   0)
+
+# Uncomment this if you want to use SQL database 
+# for persistent storage and comment the previous line
+#modparam("usrloc", "db_mode", 2)
+
+# -- auth params --
+# Uncomment if you are using auth module
+#
+#modparam("auth_db", "calculate_ha1", yes)
+#
+# If you set "calculate_ha1" parameter to yes (which true in this config), 
+# uncomment also the following parameter)
+#
+#modparam("auth_db", "password_column", "password")
+
+# -- rr params --
+# add value to ;lr param to make some broken UAs happy
+modparam("rr", "enable_full_lr", 1)
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+	setflag(1);
+	t_on_failure("1");
+	t_on_reply("1");
+	log(1, "message received\n");
+	t_relay("udp:kamailio.org:5060");
+}
+
+onreply_route[1]
+{
+	if (isflagset(1)) {
+		log(1, "onreply: flag set\n");
+	} else {
+		log(1, "onreply: flag unset\n");
+	};
+}
+
+failure_route[1] 
+{
+	if (isflagset(1)) {
+		log(1, "failure: flag set\n");
+	} else {
+		log(1, "failure: flag unset\n");
+	};
+}
+

+ 67 - 0
examples/kamailio/fork.cfg

@@ -0,0 +1,67 @@
+#
+# $Id$
+#
+# example script showing both types of forking;
+# incoming message is forked in parallel to
+# 'nobody' and 'parallel', if no positive reply
+# appears with final_response timer, nonsense
+# is retried (serial forking); than, destination
+# 'foo' is given last chance
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+
+loadmodule "sl.so"
+loadmodule "tm.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- tm params --
+# set time for which ser will be waiting for a final response;
+# fr_inv_timer sets value for INVITE transactions, fr_timer
+# for all others
+modparam("tm", "fr_inv_timer", 15 )
+modparam("tm", "fr_timer", 10 )
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+	# for testing purposes, simply okay all REGISTERs
+	if (method=="REGISTER") {
+		log("REGISTER");
+		sl_send_reply("200", "ok");
+		exit;
+	};
+	# try these two destinations first in parallel; the second
+	# destination is targeted to sink port -- that will make ser
+	# wait until timer hits
+	seturi("sip:[email protected]");
+	append_branch("sip:[email protected]:9");
+	# if we do not get a positive reply, continue at reply_route[1]
+	t_on_failure("1");
+	# forward the request to all destinations in destination set now 
+	t_relay();
+}
+
+failure_route[1] {
+	# forwarding failed -- try again at another destination 
+	append_branch("sip:[email protected]");
+	log(1,"first redirection\n");
+	# if this alternative destination fails too, proceed to reply_route[2] 
+	t_on_failure("2");
+	t_relay();
+}
+
+failure_route[2] {
+	# try out the last resort destination
+	append_branch("sip:[email protected]");
+	log(1, "second redirection\n");
+	# we no more call t_on_negative here; if this destination
+	# fails too, transaction will complete
+	t_relay();
+}

+ 31 - 0
examples/kamailio/logging.cfg

@@ -0,0 +1,31 @@
+#
+# $Id$
+#
+# logging example
+#
+
+# ------------------ module loading ----------------------------------
+
+fork=no
+port=5060
+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:.*[@:]siphub.net") {
+		log(1, "request for siphub.net received\n");
+	} else {
+		log(1, "request for other domain received\n");
+	};
+}

+ 146 - 0
examples/kamailio/msilo.cfg

@@ -0,0 +1,146 @@
+#
+# MSILO usage example
+#
+# $ID: daniel $
+#
+
+
+
+children=2
+check_via=no      # (cmd. line: -v)
+dns=off           # (cmd. line: -r)
+rev_dns=off       # (cmd. line: -R)
+
+
+# ------------------ module loading ----------------------------------
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+loadmodule "textops.so"
+
+loadmodule "sl.so"
+loadmodule "db_mysql.so"
+loadmodule "maxfwd.so"
+loadmodule "tm.so"
+loadmodule "usrloc.so"
+loadmodule "registrar.so"
+loadmodule "msilo.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- registrar params --
+
+modparam("registrar", "default_expires", 120)
+
+# -- registrar params --
+
+modparam("usrloc", "db_mode", 0)
+
+# -- msilo params --
+
+modparam("msilo", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
+
+# -- tm params --
+
+modparam("tm", "fr_timer", 10 )
+modparam("tm", "fr_inv_timer", 15 )
+modparam("tm", "wt_timer", 10 )
+
+
+route{
+	if ( !mf_process_maxfwd_header("10") )
+	{
+		sl_send_reply("483","To Many Hops");
+		exit;
+	};
+
+
+	if (uri==myself) {
+		# for testing purposes, simply okay all REGISTERs
+		# is_method("XYZ") is faster than (method=="XYZ")
+		#  but requires textops module
+		if (is_method("REGISTER"))
+		{
+			save("location");
+			log("REGISTER received -> dumping messages with MSILO\n");
+
+			# MSILO - dumping user's offline messages
+			if (m_dump())
+			{
+				log("MSILO: offline messages dumped - if they were\n");
+			}else{
+				log("MSILO: no offline messages dumped\n");
+			};
+			exit;
+		};
+
+		# backup r-uri for m_dump() in case of delivery failure
+		$avp(i:11) = $ru;
+
+		# domestic SIP destinations are handled using our USRLOC DB
+		
+		if(!lookup("location")) 
+		{
+			if (! t_newtran())
+			{
+				sl_reply_error();
+				exit;
+			};
+			# we do not care about anything else but MESSAGEs
+			if (!is_method("MESSAGE"))
+			{
+				if (!t_reply("404", "Not found")) 
+				{
+					sl_reply_error();
+				};
+				exit;
+			};
+			log("MESSAGE received -> storing using MSILO\n");
+			# MSILO - storing as offline message
+			if (m_store("$ru"))
+			{
+				log("MSILO: offline message stored\n");
+				if (!t_reply("202", "Accepted")) 
+				{
+					sl_reply_error();
+				};
+			}else{
+				log("MSILO: offline message NOT stored\n");
+				if (!t_reply("503", "Service Unavailable")) 
+				{
+					sl_reply_error();
+				};
+			};
+			exit;
+		};
+		# if the downstream UA does not support MESSAGE requests
+		# go to failure_route[1]
+		t_on_failure("1");
+		t_relay();
+		exit;
+	};
+
+	# forward anything else
+	t_relay();
+}
+
+failure_route[1] {
+	# forwarding failed -- check if the request was a MESSAGE 
+	if (!is_method("MESSAGE"))
+	{
+		exit;
+	};
+	
+	log(1,"MSILO: the downstream UA does not support MESSAGE requests ...\n");
+	# we have changed the R-URI with the contact address -- ignore it now
+	if (m_store("$avp(i:11)"))
+	{
+		log("MSILO: offline message stored\n");
+		t_reply("202", "Accepted"); 
+	}else{
+		log("MSILO: offline message NOT stored\n");
+		t_reply("503", "Service Unavailable");
+	};
+}
+
+

+ 237 - 0
examples/kamailio/nathelper.cfg

@@ -0,0 +1,237 @@
+#
+# $Id$
+#
+# simple quick-start config script including nathelper support
+
+# This default script includes nathelper support. To make it work
+# you will also have to install Maxim's RTP proxy. The proxy is enforced
+# if one of the parties is behind a NAT.
+#
+# If you have an endpoing in the public internet which is known to
+# support symmetric RTP (Cisco PSTN gateway or voicemail, for example),
+# then you don't have to force RTP proxy. If you don't want to enforce
+# RTP proxy for some destinations than simply use t_relay() instead of
+# route(1)
+#
+# Sections marked with !! Nathelper contain modifications for nathelper
+#
+# NOTE !! This config is EXPERIMENTAL !
+#
+# ----------- global configuration parameters ------------------------
+
+debug=3         # debug level (cmd line: -dddddddddd)
+fork=yes
+log_stderror=no	# (cmd line: -E)
+
+/* Uncomment these lines to enter debugging mode 
+fork=no
+log_stderror=yes
+*/
+
+check_via=no	# (cmd. line: -v)
+dns=no           # (cmd. line: -r)
+rev_dns=no      # (cmd. line: -R)
+port=5060
+children=4
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+# Uncomment this if you want to use SQL database
+#loadmodule "mysql.so"
+
+loadmodule "sl.so"
+loadmodule "tm.so"
+loadmodule "rr.so"
+loadmodule "maxfwd.so"
+loadmodule "usrloc.so"
+loadmodule "registrar.so"
+loadmodule "textops.so"
+loadmodule "mi_fifo.so"
+
+# Uncomment this if you want digest authentication
+# db_mysql.so must be loaded !
+#loadmodule "auth.so"
+#loadmodule "auth_db.so"
+
+# !! Nathelper
+loadmodule "nathelper.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# -- mi_fifo params --
+
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
+
+# -- usrloc params --
+
+modparam("usrloc", "db_mode",   0)
+
+# Uncomment this if you want to use SQL database 
+# for persistent storage and comment the previous line
+#modparam("usrloc", "db_mode", 2)
+
+# -- auth params --
+# Uncomment if you are using auth module
+#
+#modparam("auth_db", "calculate_ha1", yes)
+#
+# If you set "calculate_ha1" parameter to yes (which true in this config), 
+# uncomment also the following parameter)
+#
+#modparam("auth_db", "password_column", "password")
+
+# -- rr params --
+# add value to ;lr param to make some broken UAs happy
+modparam("rr", "enable_full_lr", 1)
+
+# !! Nathelper
+modparam("usrloc","nat_bflag",6)
+modparam("nathelper","sipping_bflag",8)
+modparam("nathelper", "ping_nated_only", 1)   # Ping only clients behind NAT
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	# initial sanity checks -- messages with
+	# max_forwards==0, or excessively long requests
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	};
+	if (msg:len >=  2048 ) {
+		sl_send_reply("513", "Message too big");
+		exit;
+	};
+
+	# !! Nathelper
+	# Special handling for NATed clients; first, NAT test is
+	# executed: it looks for via!=received and RFC1918 addresses
+	# in Contact (may fail if line-folding is used); also,
+	# the received test should, if completed, should check all
+	# vias for rpesence of received
+	if (nat_uac_test("3")) {
+		# Allow RR-ed requests, as these may indicate that
+		# a NAT-enabled proxy takes care of it; unless it is
+		# a REGISTER
+
+		if (is_method("REGISTER") || !is_present_hf("Record-Route")) {
+		    log("LOG: Someone trying to register from private IP, rewriting\n");
+
+		    # This will work only for user agents that support symmetric
+		    # communication. We tested quite many of them and majority is
+		    # smart enough to be symmetric. In some phones it takes a configuration
+		    # option. With Cisco 7960, it is called NAT_Enable=Yes, with kphone it is
+		    # called "symmetric media" and "symmetric signalling".
+
+		    fix_nated_contact(); # Rewrite contact with source IP of signalling
+		    if ( is_method("INVITE") ) {
+		        fix_nated_sdp("1"); # Add direction=active to SDP
+		    };
+		    force_rport(); # Add rport parameter to topmost Via
+		    setbflag(6);    # Mark as NATed
+			
+			# if you want sip nat pinging
+			# setbflag(8);
+		};
+	};
+
+	# we record-route all messages -- to make sure that
+	# subsequent messages will go through our proxy; that's
+	# particularly good if upstream and downstream entities
+	# use different transport protocol
+	if (!is_method("REGISTER")) record_route();
+
+	# subsequent messages withing a dialog should take the
+	# path determined by record-routing
+	if (loose_route()) {
+		# mark routing logic in request
+		append_hf("P-hint: rr-enforced\r\n"); 
+		route(1);
+		exit;
+	};
+
+	if (!uri==myself) {
+		# mark routing logic in request
+		append_hf("P-hint: outbound\r\n"); 
+		route(1);
+		exit;
+	};
+
+	# if the request is for other domain use UsrLoc
+	# (in case, it does not work, use the following command
+	# with proper names and addresses in it)
+	if (uri==myself) {
+
+		if (method=="REGISTER") {
+
+# Uncomment this if you want to use digest authentication
+#			if (!www_authorize("siphub.org", "subscriber")) {
+#				www_challenge("siphub.org", "0");
+#				return;
+#			};
+
+			save("location");
+			exit;
+		};
+
+		lookup("aliases");
+		if (!uri==myself) {
+			append_hf("P-hint: outbound alias\r\n"); 
+			route(1);
+			exit;
+		};
+
+		# native SIP destinations are handled using our USRLOC DB
+		if (!lookup("location")) {
+			sl_send_reply("404", "Not Found");
+			exit;
+		};
+	};
+	append_hf("P-hint: usrloc applied\r\n"); 
+	route(1);
+}
+
+route[1] 
+{
+	# !! Nathelper
+	if (uri=~"[@:](192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)" && !search("^Route:")){
+		sl_send_reply("479", "We don't forward to private IP addresses");
+		exit;
+	};
+
+	# if client or server know to be behind a NAT, enable relay
+	if (isbflagset(6)) {
+		force_rtp_proxy();
+	};
+
+	# NAT processing of replies; apply to all transactions (for example,
+	# re-INVITEs from public to private UA are hard to identify as
+	# NATed at the moment of request processing); look at replies
+	t_on_reply("1");
+
+	# send it out now; use stateful forwarding as it works reliably
+	# even for UDP2TCP
+	if (!t_relay()) {
+		sl_reply_error();
+	};
+}
+
+# !! Nathelper
+onreply_route[1] {
+	# NATed transaction ?
+	if (isbflagset(6) && status =~ "(183)|2[0-9][0-9]") {
+		fix_nated_contact();
+		force_rtp_proxy();
+	# otherwise, is it a transaction behind a NAT and we did not
+	# know at time of request processing ? (RFC1918 contacts)
+	} else if (nat_uac_test("1")) {
+		fix_nated_contact();
+	};
+}
+

+ 148 - 0
examples/kamailio/pstn.cfg

@@ -0,0 +1,148 @@
+#
+# $Id$
+#
+# example: ser configured as PSTN gateway guard; PSTN gateway is located
+# at 192.168.0.10
+#
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+loadmodule "sl.so"
+loadmodule "tm.so"
+loadmodule "acc.so"
+loadmodule "rr.so"
+loadmodule "maxfwd.so"
+loadmodule "db_mysql.so"
+loadmodule "auth.so"
+loadmodule "auth_db.so"
+loadmodule "group.so"
+loadmodule "uri.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+modparam("auth_db", "db_url","mysql://kamailio:kamailiorw@localhost/kamailio")
+modparam("auth_db", "calculate_ha1", yes)
+modparam("auth_db", "password_column", "password")
+
+# -- acc params --
+modparam("acc", "log_level", 1)
+# that is the flag for which we will account -- don't forget to
+# set the same one :-)
+modparam("acc", "log_flag", 1 )
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	/* ********* ROUTINE CHECKS  ********************************** */
+
+	# filter too old messages
+	if (!mf_process_maxfwd_header("10")) {
+		log("LOG: Too many hops\n");
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	};
+	if (msg:len >=  2048 ) {
+		sl_send_reply("513", "Message too big");
+		exit;
+	};
+
+	/* ********* RR ********************************** */
+
+	/* grant Route routing if route headers present */
+	if (loose_route()) { t_relay(); exit; };
+	
+	/* record-route INVITEs -- all subsequent requests must visit us */
+	if (method=="INVITE") {
+		record_route();
+	};
+
+	# now check if it really is a PSTN destination which should be handled
+	# by our gateway; if not, and the request is an invitation, drop it --
+	# we cannot terminate it in PSTN; relay non-INVITE requests -- it may
+	# be for example BYEs sent by gateway to call originator
+	if (!uri=~"sip:\+?[0-9]+@.*") {
+		if (method=="INVITE") {
+			sl_send_reply("403", "Call cannot be served here");
+		} else {
+			forward();
+		};
+		exit;
+	}; 
+
+	# account completed transactions via syslog
+	setflag(1);
+
+	# free call destinations ... no authentication needed
+	if ( is_user_in("Request-URI", "free-pstn")  /* free destinations */
+			||  uri=~"sip:[79][0-9][0-9][0-9]@.*"  /* local PBX */
+			|| uri=~"sip:98[0-9][0-9][0-9][0-9]") {
+		log("free call");
+	} else if (src_ip==192.168.0.10) {
+		# our gateway doesn't support digest authentication;
+		# verify that a request is coming from it by source
+		# address
+		log("gateway-originated request");
+	} else {
+		# in all other cases, we need to check the request against
+		# access control lists; first of all, verify request
+		# originator's identity
+
+		if (!proxy_authorize(	"gateway" /* realm */,
+				"subscriber" /* table name */))  {
+			proxy_challenge( "gateway" /* realm */, "0" /* no qop */ );
+			exit;
+		};
+
+		# authorize only for INVITEs -- RR/Contact may result in weird
+		# things showing up in d-uri that would break our logic; our
+		# major concern is INVITE which causes PSTN costs 
+
+		if (method=="INVITE") {
+
+			# does the authenticated user have a permission for local
+			# calls (destinations beginning with a single zero)? 
+			# (i.e., is he in the "local" group?)
+			if (uri=~"sip:0[1-9][0-9]+@.*") {
+				if (!is_user_in("credentials", "local")) {
+					sl_send_reply("403", "No permission for local calls"); 
+					exit;
+				};
+			# the same for long-distance (destinations begin with two zeros")
+			} else if (uri=~"sip:00[1-9][0-9]+@.*") {
+				if (!is_user_in("credentials", "ld")) {
+					sl_send_reply("403", " no permission for LD ");
+					exit;
+				};
+			# the same for international calls (three zeros)
+			} else if (uri=~"sip:000[1-9][0-9]+@.*") {
+				if (!is_user_in("credentials", "int")) {
+					sl_send_reply("403", "International permissions needed");
+					exit;
+				};
+			# everything else (e.g., interplanetary calls) is denied
+			} else {
+				sl_send_reply("403", "Forbidden");
+				exit;
+			};
+
+		}; # INVITE to authorized PSTN
+
+	}; # authorized PSTN
+
+	# if you have passed through all the checks, let your call go to GW!
+
+	rewritehostport("192.168.0.10:5060");
+
+	# forward the request now
+	if (!t_relay()) {
+		sl_reply_error(); 
+		exit; 
+	};
+
+}

+ 33 - 0
examples/kamailio/redirect.cfg

@@ -0,0 +1,33 @@
+#
+# $Id$
+#
+# this example shows use of ser as stateless redirect server
+#
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+loadmodule "sl.so"
+
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+	# for testing purposes, simply okay all REGISTERs
+	if (method=="REGISTER") {
+		log("REGISTER");
+		sl_send_reply("200", "ok");
+		return;
+	};
+	# rewrite current URI, which is always part of destination ser
+	rewriteuri("sip:[email protected]:9");
+	# append one more URI to the destination ser
+	append_branch("sip:[email protected]:9");
+	# redirect now
+	sl_send_reply("300", "Redirect");
+}
+

+ 76 - 0
examples/kamailio/replicate.cfg

@@ -0,0 +1,76 @@
+#
+# $Id$
+#
+# demo script showing how to set-up usrloc replication
+#
+
+# ----------- global configuration parameters ------------------------
+
+debug=3          # debug level (cmd line: -dddddddddd)
+fork=no
+log_stderror=yes # (cmd line: -E)
+
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+loadmodule "db_mysql.so"
+loadmodule "sl.so"
+loadmodule "tm.so"
+loadmodule "maxfwd.so"
+loadmodule "usrloc.so"
+loadmodule "registrar.so"
+loadmodule "auth.so"
+loadmodule "auth_db.so"
+
+# ----------------- setting module-specific parameters ---------------
+
+# digest generation secret; use the same in backup server;
+# also, make sure that the backup server has sync'ed time
+modparam("auth", "secret", "alsdkhglaksdhfkloiwr")
+
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	# initial sanity checks -- messages with
+	# max_forwars==0, or excessively long requests
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	};
+	if (msg:len >=  2048 ) {
+		sl_send_reply("513", "Message too big");
+		exit;
+	};
+
+	# if the request is for other domain use UsrLoc
+	# (in case, it does not work, use the following command
+	# with proper names and addresses in it)
+	if (uri==myself) {
+
+		if (method=="REGISTER") {
+
+			# verify credentials
+			if (!www_authorize("foo.bar", "subscriber")) {
+				www_challenge("foo.bar", "0");
+				exit;
+			};
+
+			# if ok, update contacts and ...
+			save("location");
+			# ... if this REGISTER is not a replica from our
+			# peer server, replicate to the peer server
+			if (!src_ip==backup.foo.bar) {
+				t_replicate("sip:backup.foo.bar:5060");
+			};
+			exit;
+		};
+		# do whatever else appropriate for your domain
+		log("non-REGISTER\n");
+	};
+}
+

+ 65 - 0
examples/kamailio/serial_183.cfg

@@ -0,0 +1,65 @@
+#
+# $Id$
+#
+# this example shows how to use forking on failure
+#
+
+log_stderror=1
+fork=no
+listen=192.168.2.16
+debug=3
+# ------------------ module loading ----------------------------------
+
+#set module path
+mpath="/usr/local/lib/kamailio/modules/"
+
+# Uncomment this if you want to use SQL database
+loadmodule "tm.so"
+loadmodule "sl.so"
+loadmodule "maxfwd.so"
+# -------------------------  request routing logic -------------------
+
+# main routing logic
+
+route{
+
+	# initial sanity checks -- messages with
+	# max_forwards==0, or excessively long requests
+	if (!mf_process_maxfwd_header("10")) {
+		sl_send_reply("483","Too Many Hops");
+		exit;
+	};
+	if (msg:len >=  2048 ) {
+		sl_send_reply("513", "Message too big");
+		exit;
+	};
+
+	/* skip register for testing purposes */
+	if (method=="REGISTER") { sl_send_reply("200", "ok"); exit; };
+
+	if (!method=="ACK")
+		log(1, "forwarding now to primary destination\n");
+	if (method=="INVITE") {
+		rewriteuri("sip:[email protected]:5064");
+		# if transaction broken, try other an alternative
+		# route
+		t_on_failure("1");
+		# if a provisional came, stop alternating
+		t_on_reply("1");
+	};
+	t_relay();
+}
+
+failure_route[1] {
+	log(1, "trying at alternate destination\n");
+	append_branch("sip:[email protected]:5064");
+	t_relay();
+}
+
+onreply_route[1] {
+	log(1, "reply came in\n");
+	if (status=~"18[0-9]")  {
+		log(1, "provisional -- resetting negative failure\n");
+		t_on_failure("0");
+	};
+}

+ 11 - 0
examples/kamailio/web_im/README

@@ -0,0 +1,11 @@
+#
+# $Id$
+#
+
+This examle illustrate how to use ser's FIFO interface
+to initate sending an instant message from a webpage.
+
+To enable this example, you need
+- web server with PHP support
+- install the example webpages on the server
+- have running ser with enabled fifo

+ 40 - 0
examples/kamailio/web_im/click_to_dial.html

@@ -0,0 +1,40 @@
+<html>
+<!-- $Id$ -->
+<header>
+<title>
+Click-To-Dial
+</title>
+</header>
+
+<body>
+<h1>
+Click-To-Dial (using REFER)
+</h1>
+
+<i>Unfortunately, this example does not work. The reason is use of
+REFER for third-party call-control has not been standardized due
+to resistance of proponents of B2BUA use (which is somewhat bloated
+and not always operational).
+</i>
+
+<form method=POST action=click_to_dial.php>
+<table>
+<tr>
+<td>
+Caller's SIP Address
+<td>
+<input name=caller>
+<tr>
+<td>
+Callee's SIP Address
+<td>
+<input name=callee>
+<tr>
+<td>Click to dial
+<td>
+<input type=submit value=now>
+</table>
+</form>
+
+
+</body>

+ 76 - 0
examples/kamailio/web_im/click_to_dial.php

@@ -0,0 +1,76 @@
+<html>
+<!-- $Id$ -->
+<header>
+<title>
+Click-To-Dial
+</title>
+</header>
+
+<body>
+<h1>
+Click-To-Dial
+</h1>
+
+<?php
+
+/* config values */
+$web_contact="sip:[email protected]";
+$fifo="/tmp/kamailio_fifo";
+$signature="web_dialer_0.1.0";
+
+/* open reply fifo */
+$myfilename="webfifo_".rand();
+$mypath="/tmp/".$myfilename;
+$outbound_proxy=".";
+
+
+$caller = $_POST['caller'];
+$callee = $_POST['callee'];
+
+echo "Initiating your request...<p>";
+/* open fifo now */
+$fifo_handle=fopen( $fifo, "w" );
+if (!$fifo_handle) {
+    exit ("Sorry -- cannot open fifo: ".$fifo);
+}
+
+/* construct FIFO command */
+
+$fifo_cmd=":t_uac_dlg:".$myfilename."\n".
+    "REFER\n".
+     $caller."\n".
+	 $outbound_proxy."\n".
+	 ".\n".
+     "\"From: ".$web_contact."\r\n".
+     "To: ".$callee."\r\n".
+     "p-version: ".$signature."\r\n".
+    "Contact: ".$web_contact."\r\n".
+    "Referred-By: ".$web_contact."\r\n".
+	"Refer-To: ".$callee."\r\n".
+	"\"\n\n";
+	
+    
+/* create fifo for replies */
+system("mkfifo -m 666 ".$mypath );
+
+/* write fifo command */
+if (fwrite( $fifo_handle, $fifo_cmd)==-1) {
+    unlink($mypath);
+    fclose($fifo_handle);
+    exit("Sorry -- fifo writing error");
+}
+fclose($fifo_handle);
+
+/* read output now */
+if (readfile( $mypath )==-1) {
+    unlink($mypath);
+	exit("Sorry -- fifo reading error");
+}
+unlink($mypath);
+echo "<p>Thank you for using click-to-dial<p>";
+
+?>
+
+</body>
+</html>
+

+ 37 - 0
examples/kamailio/web_im/send_im.html

@@ -0,0 +1,37 @@
+<html>
+<!-- $Id$ -->
+<header>
+<title>
+Send IM
+</title>
+</header>
+
+<body>
+<h1>
+Send IM
+</h1>
+
+<form method=POST action=send_im.php>
+<table>
+<tr>
+<td>
+SIP Address
+<br>
+Example: [email protected]
+<td>
+<input name=sip_address>
+<tr>
+<td>
+Message
+<td>
+<textarea name=instant_message rows=6 cols=40>
+</textarea>
+<tr>
+<td>Click to send
+<td>
+<input type=submit value=submit>
+</table>
+</form>
+
+
+</body>

+ 77 - 0
examples/kamailio/web_im/send_im.php

@@ -0,0 +1,77 @@
+<html>
+<!-- $Id$ -->
+<header>
+<title>
+Send IM Status
+</title>
+</header>
+
+<body>
+<h1>
+Send IM Status
+</h1>
+
+<?php
+
+/* config values */
+$web_contact="sip:[email protected]";
+$fifo="/tmp/kamailio_fifo";
+$signature="web_im_0.1.0";
+
+/* open reply fifo */
+$myfilename="webfifo_".rand();
+$mypath="/tmp/".$myfilename;
+$outbound_proxy=".";
+
+
+$sip_address = $_POST['sip_address'];
+$instant_message = $_POST['instant_message'];
+
+
+echo "Initiating your request...<p>";
+
+/* open fifo now */
+$fifo_handle=fopen( $fifo, "w" );
+if (!$fifo_handle) {
+    exit ("Sorry -- cannot open fifo: ".$fifo);
+}
+
+/* construct FIFO command */
+$fifo_cmd=":t_uac_dlg:".$myfilename."\n".
+    "MESSAGE\n".
+    $sip_address."\n".
+	$outbound_proxy."\n".
+    ".\n".
+    "\"From: ".$web_contact."\r\n".
+	"To: ".$sip_address."\r\n".
+	"p-version: ".$signature."\r\n".
+    "Contact: ".$web_contact."\r\n".
+    "Content-Type: text/plain; charset=UTF-8\r\n".
+    "\"\n".
+    "\"".$instant_message."\"".
+  	"\n\n";  
+
+/* create fifo for replies */
+system("mkfifo -m 666 ".$mypath );
+
+/* write fifo command */
+if (fwrite( $fifo_handle, $fifo_cmd)==-1) {
+    unlink($mypath);
+    fclose($fifo_handle);
+    exit("Sorry -- fifo writing error");
+}
+fclose($fifo_handle);
+
+/* read output now */
+if (readfile( $mypath )==-1) {
+    unlink($mypath);
+	exit("Sorry -- fifo reading error");
+}
+unlink($mypath);
+echo "<p>Thank you for using IM<p>";
+
+?>
+
+</body>
+</html>
+