[Serusers] Call transfer, ser not send BYE after REFER

Murděj Ukrutný murdej.ukrutny at centrum.cz
Wed May 17 14:34:27 CEST 2006


Hello,

i have problem with call transfer. I try

A call to B,
B receive call,
B transfer A to B

truncate ngrep port 5060:

INVITE B
From: A
To: B

REFER A
From: B
To: A
Refer-To: C
Referred-by: B

INVITE C
From: A
To: C

Problem: ser not send BYE after REFER

My ser.cfg:

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
fifo="/tmp/ser_fifo"
fifo_mode=0666
#mhomed=yes
listen=195.137.182.11

# ------------------ module loading ----------------------------------

# Uncomment this if you want to use SQL database

loadmodule "/usr/lib/ser/modules/mysql.so"
loadmodule "/usr/lib/ser/modules/sl.so"
loadmodule "/usr/lib/ser/modules/tm.so"
loadmodule "/usr/lib/ser/modules/rr.so"
loadmodule "/usr/lib/ser/modules/maxfwd.so"
loadmodule "/usr/lib/ser/modules/usrloc.so"
loadmodule "/usr/lib/ser/modules/registrar.so"
loadmodule "/usr/lib/ser/modules/textops.so"
loadmodule "/usr/lib/ser/modules/uri_db.so"
loadmodule "/usr/lib/ser/modules/auth.so"
loadmodule "/usr/lib/ser/modules/auth_db.so"
loadmodule "/usr/lib/ser/modules/nathelper.so"
loadmodule "/usr/lib/ser/modules/group.so"
#loadmodule "SER_MODULES_DIR/acc.so"
loadmodule "/usr/lib/ser/modules/acc_db.so"

# ----------------- setting module-specific parameters ---------------

# -- 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 --

modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth", "nonce_expire", 300)
modparam("auth", "rpid_prefix", "<sip:")
modparam("auth", "rpid_suffix", "@GW_IP_3>;party=calling;id-type=subscriber;screen=yes;privacy=off")

# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)

# !! Nathelper
modparam("registrar", "nat_flag", 6)
modparam("nathelper", "natping_interval", 30) # Ping interval 30 s
modparam("nathelper", "ping_nated_only", 1)   # Ping only clients behind NAT

# Acc

modparam("acc", "report_ack", 1)
modparam("acc", "log_level", 1)
modparam("acc", "failed_transactions", 1)
modparam("acc", "db_flag", 2)
modparam("acc", "db_missed_flag", 3)
modparam("acc", "log_fmt", "fisum")

# Nemelo by se to objevit v logu
#modparam("acc", "log_flag", FLAG_ACC)
#modparam("acc", "log_missed_flag", FLAG_MISSED)

# Nastaveni spojeni k Mysql pro moduly

modparam("group|usrloc|uri_db|acc", "db_url", "mysql://ser:ser@localhost/ser")

# -------------------------  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");
		break;
	};
	if (msg:len >=  max_len ) {
		sl_send_reply("513", "Message too big");
		break;
	};

	# Do acc se zapisuji vsechny nasledujici pozadavky
	if (method == "INVITE" || method == "CANCEL" || method == "BYE" || method == "ACK") {
		setflag(2);
	};


	# Uprava hlavicky Server
	remove_hf("Server");
	append_hf("Server: EMEA Telecom IBM S2 SIP Server\r\n");
				
        # !! 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 (method == "REGISTER" || ! search("^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 (method == "INVITE") {
				fix_nated_sdp("1"); # Add direction=active to SDP
			};
			force_rport(); # Add rport parameter to topmost Via
			setflag(6);    # Mark as NATed
		};
	};

	# 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 (!(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);
		break;
		# account all BYEs
		if (method=="BYE") setflag(2);
	};

	if (!uri==myself) {
		# mark routing logic in request
		append_hf("P-hint: outbound\r\n"); 
		route(1);
		break;
	};

	# 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") {
			# Kontrola prihlaseni podle tabulky subscribler

			if (!www_authorize("sip.ahoj.cz", "subscriber")) {
				www_challenge("sip.ahoj.cz", "0");
				break;
			};
			save("location");
			break;
		};
		
		lookup("aliases");
		if (!uri==myself) {
			append_hf("P-hint: outbound alias\r\n"); 
			route(1);
			break;
		};

		# native SIP destinations are handled using our USRLOC DB
		if (!lookup("location")) {
			if (does_uri_exist()) {
				# Existuje na serveru ale neni online
				sl_send_reply("404", "Not Found");
				break;
			} else {
				# neni na tomto serveru, pujde do pstn, nebude se pouzivat rtpproxy
				resetflag(6);
				setflag(1);
			};
		};
	};
	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");
	    break;
        };
	
	# if client or server know to be behind a NAT, enable relay
	if (isflagset(6)) {
	    force_rtp_proxy();
	    append_hf("X-rtpproxy: yes\r\n");
	};

	# 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

	route(2);
}
route[2] {
	if ((method == "INVITE") && (uri =~ "sip:S302_")) {
		sl_send_reply("302", "Rewrited");
		break;
	};
	
	if (method == "INVITE") {
		if (src_ip == "xxx.xxx.xxx.xxx") {
			setflag(4);
			append_hf("X-s2router-source: gateway-pstn\r\n");
			log("LOG: From PSTN\n");
		};
		
		if (!is_user_in("Request-URI", "free-pstn")) {
			if (!isflagset(4) && !proxy_authorize("DIGEST_REALM", "subscriber"))  {
				proxy_challenge("DIGEST_REALM", "0");
				break;
			};
			# let's check from=id ... avoids accounting confusion
			if (!isflagset(4) && !check_from()) {
				log("LOG: From Cheating attempt\n");
				sl_send_reply("403", "That is ugly -- use From=id next time (gw)");
				break;
			};
		};
	};

	# Pokud neni cislo registrovane na serveru zkus pstn	
	if (isflagset(1)) {
		# Vola jen na cisla
		if (uri =~ "^[a-zA-Z]+:[0-9]+@") {
			route(4);
		} else {
			sl_send_reply("604", "Does Not Exist Anywhere");
		};
		break;
	};
	route(3);
}
route[4] {
	log(1, "Jedu pres PSTN");
	if (!(method == "INVITE" || method == "ACK" || method == "CANCEL" || method == "OPTIONS" || method == "BYE")) {
		sl_send_reply("500", "only VoIP methods accepted for GW");
		break;
	};
	rewritehostport("195.122.201.61:5060");
	# Acc
	setflag(2);

	route(3);
}
route[3] {
	if (!t_relay()) {
		sl_reply_error();
	};
	break;
}

# !! Nathelper
onreply_route[1] {
	
	# NATed transaction ?
	if (isflagset(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();
	};
}


Any idea?

Thank
--
    Murdej Ukrutny




More information about the sr-users mailing list