Hi,
 
Can anybody help me with these duplicate messages?
I guess the first message should be removed from the db, since it got a reply 202.
Despite that, it end up again in the db.
Can you help me what I am doing wrong?
 
Many thanks
Marc
 

From: proycon@hotmail.com
To: sr-users@lists.sip-router.org
Date: Tue, 3 Jun 2014 21:38:32 +0000
Subject: [SR-Users] MSILO - dumped messages get duplicated

Hi,

I have a Kamailio 3.2 setup up and running.
Recently I configured msilo for offline message store. Essentialy the setup runs fine.

Messages to users without location info getting stored.
In case the user has location info, but cannot be reached, I made failover_route, so the messages getting stored in this case too.
Messages getting dumped at the next REGISTER.

However, I have a group of new mobile clients, with unstable connection.
It happens many times that they send a REGISTER, but the connection brakes afterwards.

It this case the message is getting dumped, but since it cannot be delivered, it runs on the failover_route which stores the message again.
However, the previous message is not removed from the db, so the same message is now twice in the db.
Next time the message either gets delivered in double, or in case of a new failure, it gets stored 2x2= four times.

I need to avoid this duplicates but still make sure the message get delivered sooner or later.
Any help is highly appreciated.

Here is my routing table:

thanks
Marc

####### Routing Logic ########


# Main SIP request routing logic
# - processing of any incoming SIP request starts with this route
route {

	# per request initial checks
	route(REQINIT);

	# NAT detection
	route(NAT);

	# handle requests within SIP dialogs
	route(WITHINDLG);

	### only initial requests (no To tag)

	# CANCEL processing
	if (is_method("CANCEL"))
	{
		if (t_check_trans())
			t_relay();
		exit;
	}

	if (is_method("MESSAGE"))
        {
         log(1,"-------------------------------------------------------->WE HAVE A NEW MESSAGE\n");
         route(MSILO_MESSAGE);
        }
	
	t_check_trans();

	# authentication
	route(AUTH);

	# record routing for dialog forming requests (in case they are routed)
	# - remove preloaded route headers
	remove_hf("Route");
	if (is_method("INVITE|SUBSCRIBE"))
		record_route();

	# account only INVITEs
	if (is_method("INVITE"))
	{
		setflag(FLT_ACC); # do accounting
	}

	# dispatch requests to foreign domains
	route(SIPOUT);

	### requests for my local domains

	# handle presence related requests
	route(PRESENCE);

	# handle registrations
	route(REGISTRAR);

	if ($rU==$null)
	{
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}

	# dispatch destinations to PSTN
	route(PSTN);

	# user location service
	route(LOCATION);

	route(RELAY);
}


route[RELAY] {
#!ifdef WITH_NAT
	if (check_route_param("nat=yes")) {
		setbflag(FLB_NATB);
	}
	if (isflagset(FLT_NATS) || isbflagset(FLB_NATB)) {
		route(RTPPROXY);
	}
#!endif


	/* example how to enable some additional event routes */
	if (is_method("INVITE")) {
		#t_on_branch("BRANCH_ONE");
		t_on_reply("REPLY_ONE");
		t_on_failure("FAIL_ONE");
	}

	if (!t_relay()) {
		sl_reply_error();
	}
	exit;
}

##storing offline messages
route[MSILO_MESSAGE]{
	if (lookup("location")){
	t_on_failure("FAIL_MESSAGE");
	t_relay();
	xlog("L_NOTICE","---------------------------------MI: ($mi), MB: ($mb)\n");
	}else{
		xlog("L_NOTICE","------------------MESSAGE PROCESSING: location not found, storing offline message ID: ($ru)\n");
		m_store("$ru");
		sl_send_reply("202", "ACCEPTED");
		
		xlog("L_NOTICE","------------------MESSAGE PROCESSING: location not found, stored offline message ID: ($ru)\n");
};
	exit;
};

failure_route[FAIL_MESSAGE]{

    xlog("L_NOTICE","------------------MESSAGE PROCESSING: user cannot be reached, storing offline message ID: ($ou)\n");
    m_store("$ou");
    t_reply("202", "ACCEPTED");
    xlog("L_NOTICE","------------------MESSAGE PROCESSING: user cannot be reached, stored offline message ID: ($ou)\n");
    exit;
    }




# Per SIP request initial checks
route[REQINIT] {
#!ifdef WITH_ANTIFLOOD
	# flood dection from same IP and traffic ban for a while
	# be sure you exclude checking trusted peers, such as pstn gateways
	# - local host excluded (e.g., loop to self)
	if(src_ip!=myself)
	{
		if($sht(ipban=>$si)!=$null)
		{
			# ip is already blocked
			xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
			exit;
		}
		if (!pike_check_req())
		{
			xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
			$sht(ipban=>$si) = 1;
			exit;
		}
	}
#!endif

	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}

	if(!sanity_check("1511", "7"))
	{
		xlog("Malformed SIP message from $si:$sp\n");
		exit;
	}
}

# Handle requests within SIP dialogs
route[WITHINDLG] {
	if (has_totag()) {
		# sequential request withing a dialog should
		# take the path determined by record-routing
		if (loose_route()) {
			if (is_method("BYE")) {
				setflag(FLT_ACC); # do accounting ...
				setflag(FLT_ACCFAILED); # ... even if the transaction fails
			}
			route(RELAY);
		} else {
			if (is_method("SUBSCRIBE") && uri == myself) {
				# in-dialog subscribe requests
				route(PRESENCE);
				exit;
			}
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
					# no loose-route, but stateful ACK;
					# must be an ACK after a 487
					# or e.g. 404 from upstream server
					t_relay();
					exit;
				} else {
					# ACK without matching transaction ... ignore and discard
					exit;
				}
			}
			sl_send_reply("404","Not here");
		}
		exit;
	}
}

# Handle SIP registrations
route[REGISTRAR] {
	if (is_method("REGISTER"))
	{
	
		
		if(isflagset(FLT_NATS))
		{
			setbflag(FLB_NATB);
			# uncomment next line to do SIP NAT pinging 
			setbflag(FLB_NATSIPPING);
		}
		if (!save("location"))
			sl_reply_error();
			# MSILO - dumping user's offline messages
                        m_dump();
                        log(1,"-------------------------MESSAGE PROCESSING: dumping offline messages\n");
                        
                        exit;
	}
}

# USER location service
route[LOCATION] {

#!ifdef WITH_ALIASDB
	# search in DB-based aliases
	alias_db_lookup("dbaliases");
#!endif

	if (!lookup("location")) {
		switch ($rc) {
			case -1:
			case -3:
				t_newtran();
				t_reply("404", "Not Found");
				exit;
			case -2:
				sl_send_reply("405", "Method Not Allowed");
				exit;
		}
	}

	# when routing via usrloc, log the missed calls also
	if (is_method("INVITE"))
	{
		setflag(FLT_ACCMISSED);
	}
}

# Presence server route
route[PRESENCE] {
	if(!is_method("PUBLISH|SUBSCRIBE"))
		return;

#!ifdef WITH_PRESENCE
	if (!t_newtran())
	{
		sl_reply_error();
		exit;
	};

	if(is_method("PUBLISH"))
	{
		handle_publish();
		t_release();
	}
	else
	if( is_method("SUBSCRIBE"))
	{
		handle_subscribe();
		t_release();
	}
	exit;
#!endif
	
	# if presence enabled, this part will not be executed
	if (is_method("PUBLISH") || $rU==$null)
	{
		sl_send_reply("404", "Not here");
		exit;
	}
	return;
}

# Authentication route
route[AUTH] {
#!ifdef WITH_AUTH
	if (is_method("REGISTER"))
	{
		# authenticate the REGISTER requests (uncomment to enable auth)
		if (!www_authorize("$td", "subscriber"))
		{
			www_challenge("$td", "0");
			exit;
		}

		if ($au!=$tU)
		{
			sl_send_reply("403","Forbidden auth ID");
			exit;
		}
	} else {

#!ifdef WITH_IPAUTH
		if(allow_source_address())
		{
			# source IP allowed
			return;
		}
#!endif

		# authenticate if from local subscriber
		if (from_uri==myself)
		{
			if (!proxy_authorize("$fd", "subscriber")) {
				proxy_challenge("$fd", "0");
				exit;
			}
			if (is_method("PUBLISH"))
			{
				if ($au!=$tU) {
					sl_send_reply("403","Forbidden auth ID");
					exit;
				}
			} else {
				if ($au!=$fU) {
					sl_send_reply("403","Forbidden auth ID");
					exit;
				}
			}

			consume_credentials();
			# caller authenticated
		} else {
			# caller is not local subscriber, then check if it calls
			# a local destination, otherwise deny, not an open relay here
			if (!uri==myself)
			{
				sl_send_reply("403","Not relaying");
				exit;
			}
		}
	}
#!endif
	return;
}

# Caller NAT detection route
route[NAT] {
#!ifdef WITH_NAT
	force_rport();
	if (nat_uac_test("19")) {
		if (method=="REGISTER") {
			fix_nated_register();
		} else {
			fix_nated_contact();
		}
		setflag(FLT_NATS);
	}
#!endif
	return;
}

# RTPProxy control
route[RTPPROXY] {
#!ifdef WITH_NAT
	if (is_method("BYE")) {
		unforce_rtp_proxy();
	} else if (is_method("INVITE")){
	
		rtpproxy_offer();
	}
	if (!has_totag()) add_rr_param(";nat=yes");
#!endif
	return;
}

# Routing to foreign domains
route[SIPOUT] {
	if (!uri==myself)
	{
		append_hf("P-hint: outbound\r\n");
		route(RELAY);
	}
}

# PSTN GW routing
route[PSTN] {
#!ifdef WITH_PSTN
	# check if PSTN GW IP is defined
	if (strempty($sel(cfg_get.pstn.gw_ip))) {
		xlog("SCRIPT: PSTN rotuing enabled but pstn.gw_ip not defined\n");
		return;
	}

	# route to PSTN dialed numbers starting with '+' or '00'
	#     (international format)
	# - update the condition to match your dialing rules for PSTN routing
	if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))
		return;

	# only local users allowed to call
	if(from_uri!=myself) {
		sl_send_reply("403", "Not Allowed");
		exit;
	}

	$ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);

	route(RELAY);
	exit;
#!endif

	return;
}

# XMLRPC routing
#!ifdef WITH_XMLRPC
route[XMLRPC]
{
	# allow XMLRPC from localhost
	if ((method=="POST" || method=="GET")
			&& (src_ip==127.0.0.1)) {
		# close connection only for xmlrpclib user agents (there is a bug in
		# xmlrpclib: it waits for EOF before interpreting the response).
		if ($hdr(User-Agent) =~ "xmlrpclib")
			set_reply_close();
		set_reply_no_connect();
		dispatch_rpc();
		exit;
	}
	send_reply("403", "Forbidden");
	exit;
}
#!endif

# Sample branch router
branch_route[BRANCH_ONE] {
	xdbg("new branch at $ru\n");
}

# Sample onreply route
onreply_route[REPLY_ONE] {
	xdbg("incoming reply\n");
#!ifdef WITH_NAT
	if ((isflagset(FLT_NATS) || isbflagset(FLB_NATB))
			&& status=~"(183)|(2[0-9][0-9])") {

		rtpproxy_answer();
	}
	if (isbflagset("6")) {
		fix_nated_contact();
	}
#!endif
}

# Sample failure route
failure_route[FAIL_ONE] {
#!ifdef WITH_NAT
	if (is_method("INVITE")
			&& (isbflagset(FLB_NATB) || isflagset(FLT_NATS))) {
		unforce_rtp_proxy();
	}
#!endif

	if (t_is_canceled()) {
		exit;
	}

	# uncomment the following lines if you want to block client 
	# redirect based on 3xx replies.
	##if (t_check_status("3[0-9][0-9]")) {
	##t_reply("404","Not found");
	##	exit;
	##}

	# uncomment the following lines if you want to redirect the failed 
	# calls to a different new destination
	##if (t_check_status("486|408")) {
	##	sethostport("192.168.2.100:5060");
	##	append_branch();
	##	# do not set the missed call flag again
	##	t_relay();
	##}
}




_______________________________________________ SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list sr-users@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users