<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>Hi,<BR> <BR>Can anybody help me with these duplicate messages?<BR>I guess the first message should be removed from the db, since it got a reply 202.<BR>Despite that, it end up again in the db.<BR>Can you help me what I am doing wrong?<BR> <BR>Many thanks<BR>Marc<br> <BR><div><hr id="stopSpelling">From: proycon@hotmail.com<br>To: sr-users@lists.sip-router.org<br>Date: Tue, 3 Jun 2014 21:38:32 +0000<br>Subject: [SR-Users] MSILO - dumped messages get duplicated<br><br>

<style><!--
.ExternalClass .ecxhmmessage P {
padding:0px;
}

.ExternalClass body.ecxhmmessage {
font-size:12pt;
font-family:Calibri;
}

--></style>
<div dir="ltr">Hi,<br><br>I have a Kamailio 3.2 setup up and running. <br>Recently I configured msilo for offline message store. Essentialy the setup runs fine. <br><br>Messages to users without location info getting stored.<br>In case the user has location info, but cannot be reached, I made failover_route, so the messages getting stored in this case too.<br>Messages getting dumped at the next REGISTER.<br><br>However, I have a group of new mobile clients, with unstable connection.<br>It happens many times that they send a REGISTER, but the connection brakes afterwards.<br><br>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.<br>However, the previous message is not removed from the db, so the same message is now twice in the db.<br>Next time the message either gets delivered in double, or in case of a new failure, it gets stored 2x2= four times.<br><br>I need to avoid this duplicates but still make sure the message get delivered sooner or later.<br>Any help is highly appreciated.<br><br>Here is my routing table:<br><br>thanks<br>Marc<br><br><pre>####### 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();
        ##}
}
</pre><br><br><br>                                        </div>
<br>_______________________________________________
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</div>                                         </div></body>
</html>