[Serusers] Audio Cut Through Issue

Brian J. Rathman brian at strata-com.com
Thu Nov 18 20:35:25 CET 2004


I am experiencing an issue with Cisco ATA186's behind NAT where when they place a call, they can not hear the called party until they speak. Since the voice cut through does eventually happen once you speak, I believe it may just be a small code issue with my ser.cfg file. This is important to me because the application I am implementing has customers using the ATA to call into an IVR platform. The problem is that they never hear the IVR until they say something. Any suggestions would be greatly appreciate. I am attaching my ser.cfg file which has been modified from an earlier version of SER. My problem may just be that I am using an antiquated config file. I am not trying to do anything crazy of special with this, so if you know of a simple working ser.cfg file that can handle registrations from behind NAT, that would be very helpful.  

Any help would be greatly appreciated.

Thanks,
Brian


# simple quick-start config script
#

# ----------- global configuration parameters ------------------------

debug=3         # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no # (cmd line: -E)

listen=6.9.1.75
listen=127.0.0.1
port=5060
children=16

check_via=yes   # (cmd. line: -v)
dns=no          # (cmd. line: -r)
rev_dns=no      # (cmd. line: -R)


fifo="/tmp/ser_fifo"

# syn_branch - Shall the server use stateful synonym branches? It is
# faster but not reboot-safe. Default is yes.
syn_branch=yes

memlog=3

# hostname matching an alias will satisfy the condition uri==myself".
alias=ari.com
alias=6.9.1.75
alias=6.9.1.16

# sip_warning - Should replies include extensive warnings? By default
# yes, it is good for trouble-shooting.
sip_warning=yes

# server_signature - Should locally-generated messages include server's
# signature? By default yes, it is good for trouble-shooting.
server_signature=yes

# reply_to_via - A hint to reply modules whether they should send reply
# to IP advertised in Via. Turned off by default, which means that
# replies are sent to IP address from which requests came.
reply_to_via=no



# mhomed -- enable calculation of outbound interface; useful on
# multihomed servers.
mhomed=0


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

# Uncomment this if you want to use SQL database
loadmodule "/usr/local/lib/ser/modules/mysql.so"

loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"

loadmodule "/usr/local/lib/ser/modules/acc.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
loadmodule "/usr/local/lib/ser/modules/uri.so"
loadmodule "/usr/local/lib/ser/modules/group.so"
loadmodule "/usr/local/lib/ser/modules/msilo.so"
loadmodule "/usr/local/lib/ser/modules/enum.so"
loadmodule "/usr/local/lib/ser/modules/nathelper.so"


# Uncomment this if you want digest authentication
# mysql.so must be loaded !
loadmodule "/usr/local/lib/ser/modules/auth.so"
loadmodule "/usr/local/lib/ser/modules/auth_db.so"

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

modparam("usrloc|group|msilo|uri", "db_url","mysql://ser:heslo@localhost/ser")

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


# -- tm params --
modparam("tm", "fr_timer", 20 )
modparam("tm", "fr_inv_timer", 90 )
modparam("tm", "wt_timer", 20 )

# -- msilo params
modparam("msilo", "registrar", "sip:registrar at ari.com")

# -- enum params --
#
modparam("enum", "domain_suffix", "e164.arpa.")

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

# -- acc params --
# that is the flag for which we will account -- don't forget to
#modparam("acc", "db_flag", 1 )
#modparam("acc", "db_missed_flag", 3 )

# -------------------------  request routing logic -------------------

# main routing logic

route {

        /* ********* ROUTINE CHECKS  ********************************** */

        # filter too old messages
        if (!mf_process_maxfwd_header("10")) {
                log(1, "LOG: Too many hops\n");
                sl_send_reply("483","Alas Too Many Hops");
                break;
        };
        if ( msg:len >= max_len ) {
                sl_send_reply("513", "Wow -- Message too large");
                break;
        };


        if (search("^(Contact|m): .*@(192\.168\.|10\.|172\.16)")) {
                log(1, "src address different than via header->NAT detected\n");
                log(1, "force_rport and fix_nated_contact and setflag(5)\n");
                #try NAT traversal, works only if the client is symmetrical
                force_rport();
                fix_nated_contact();
                append_hf("P-hint: fixed NAT contact for request\r\n");
                # flag 5 indicates that incoming request is from NATed client
                setflag(5);
        };


        /* ********* RR ********************************** */
        # to be safe, record route everything; UAs may use different
        # transport protocols and need to have SER in path

        record_route();

        setflag(1);

        # if route forces us to forward to some explicit destination,
        # do so; check however first that a cheater didn't preload
        # a gateway destination to bypass PSTN ACLs

        if (loose_route()) {
                log(1, "Loose Route\n");
                if ((uri=~"sip:[+0-9]+ at 6\.9\.1\.16")) {
                        # it is gateway -- proceed to ACLs
                        route(3);
                        break;
                };
                # route HF determined next hop; forward there
                append_hf("P-hint: rr-enforced\r\n");
                t_relay();
                break;
        };


        /*  *********  check for requests targeted out of our domain... *******
*/
        # sign of our domain: there is '@' (username) or  : (nothing) in
        # front of our domain name      ; ('.' is not there -- we handle all
        # xxx.iptel.org as outbound hosts);if none of these cases matches,
        # proceed with processing of outbound requests in route[2]
        if (!(uri==myself)) {
                log(1, "Not myself\n");
                route(2);
                break;
        };


        /* ************ requests for our domain ********** */

        /* now, the request is for sure for our domain */
        # registers always MUST be authenticated to
        # avoid stealing incoming calls
        if (method=="REGISTER") {
                # Make sure that user's dont register infinite loops
                if (search("^(Contact|m): .*@(ari\.com|6\.9\.1\.75)")) {
                        log(1, "LOG: alert: someone trying to set aor==contact\n
");
                        sl_send_reply("476", "No Server Address in Contacts Allo
wed" );
                        break;
                };

                if (search("^(Contact|m): .*6\.9\.1\.16")) {
                        log(1, "LOG: alert: protected contacts\n");
                        sl_send_reply("476", "No Server Address in Contacts Allo
wed" );
                        break;
                };

                if (!www_authorize("ari.com" /* realm */,"subscriber" /* table n
ame */ )) {
                        # challenge if none or invalid credentials
                        www_challenge(  "ari.com" /* realm */,"0" /* no qop -- s
ome phones can't deal with it */);
                        break;
                };

                # prohibit attempts to grab someone else's To address
                # using  valid credentials;
                if (!check_to()) {
                        log(1, "LOG: To Cheating attempt\n");
                        sl_send_reply("403", "That is ugly -- use To=id in REGIS
TERs");
                        break;
                };

                if (isflagset(5)) {
                        #register from nated client, save nat_flag=6
                        #in location table
                        setflag(6);
                };

                # it is an authenticated request, update Contact database now
                if (!(save("location"))) {
                        sl_reply_error();
                };

                m_dump();
                break;
        };


        # NAT Traversal Code
        if ((isflagset(5)) || (isflagset(6))) {
                log(1, "at least one of the participants is NATed->record_route\
n");
                record_route();
                log(1, "     -->setting up reply processing ->onreply_route[1]")
;
                t_on_reply("1");
                if (method=="INVITE") {
                        log(1, "     INVITE request-->force_rtp_proxy, set NATED
-INVITE flag(7)");
                        force_rtp_proxy();
                        append_hf("P-hint: request forced to rtp proxy\r\n");
                        setflag(7);
                };
        };


        # native SIP destinations are handled using our USRLOC DB
        if (lookup("location")) {
                log(1, "Native SIP destination detected\n");
                append_hf("P-hint: USRLOC\r\n");
                if (!t_relay()) {
                        sl_reply_error();
                        break;
                };
        };


        # now check if it's about PSTN destinations through our gateway;
        if (uri=~"sip:\+?[0-9][0-9]*@.*") {
                log(1, "PSTN destination to be used\n");
                route(3);
                break;
        };


#        # check whether some inventive user has uploaded  gateway
#        # contacts to UsrLoc to bypass our authorization logic
#        if (uri=~"sip:[+0-9]+ at 6\.9\.1\.16") {
#                # it is gateway -- proceed to ACLs
#                route(3);
#                break;
#        };
#
#        /* ... and also report on missed calls ... */
#        setflag(3);
#
#        # we now know we may, we know where, let it go out now!
#        append_hf("P-hint: USRLOC\r\n");
#        if (!t_relay()) {
#                sl_reply_error();
#                break;
#        };

} # route

#----------------- PSTN ----------------------------------------------
# logic for calls to the PSTN
route[3] {
        # turn accounting on
        setflag(1);

        /* require all who call PSTN to be members of the "int" group;
           apply ACLs only to INVITEs -- we don't need to protect other requests
, as they
           don't imply charges; also it could cause troubles when a call comes i
n via PSTN
           and goes to a party that can't authenticate (voicemail, other domain)
 -- BYEs would
           fail then; exempt Cisco gateway from authentication by IP address --
it does not
           support digest
        */
        if (src_ip==6.9.1.16) {
                log(1, "From ARI Gateway");
        }
        else {
                if ((method=="INVITE") && (!(src_ip==6.2.15.1))) {
                        log(1, "LOG: need to auth PSTN invite");
                        if (!proxy_authorize(   "ari.com" /* realm */,"subscribe
r" /* table name */))  {
                                proxy_challenge( "ari.com" /* realm */, "0" /* n
o qop */ );
                                break;
                        };
                        # let's check from=id ... avoids accounting confusion
                        if (method=="INVITE" & !check_from()) {
                                log(1, "LOG: From Cheating attempt\n");
                                sl_send_reply("403", "That is ugly -- use From=i
d next time (gw)");
                                break;
                        };

                        if(!is_user_in("credentials", "int")) {
                                sl_send_reply("403", "NO PSTN Privileges...");
                                break;
                        };
                        consume_credentials();

                }; # INVITE to authorized PSTN
        }

        # if you have passed through all the checks, let your call go to GW!
        log(1, "Rewriting Host and port");
        rewritehostport("6.9.1.16:5060");

        # snom conditioner
        if (method=="INVITE" && search("User-Agent: snom")) {
                replace("100rel, ", "");
        };

        t_relay_to_udp ("6.9.1.16","5060");
        t_relay_to_tcp ("6.9.1.16","5060");
        break;

}



# all incoming replies for t_onrepli-ed transactions enter here
onreply_route[1] {
        log(1, "-------------------------------------------\n");
        log(1, "onreply_route[1] entered\n");

        if (isflagset(6)) {
                log(1, "transaction was sent to a NATED client -> fix nated cont
act\n");
                fix_nated_contact();
                append_hf("P-hint: fixed NAT contact for response\r\n");
        }

        if ( (status=~"100") ) {
                log(1, "status 100 received\n");
        };

        if ( (status=~"180") ) {
                log(1, "status 180 received\n");
        };

        if ( (status=~"202") ) {
                log(1, "status 202 received\n");
        };

        if ( (status=~"200" || status=~"183") ) {
                log(1, "status 2xx or 183");
                if ( isflagset(7) ) {
                        log(1, "marked(7) as NATED-INVITE -> force_rtp_proxy \n"
);
                        force_rtp_proxy();
                        append_hf("P-hint: response forced to rtp proxy\r\n");
                };
        };
}


#------------------- OUTBOUND ----------------------------------------
# routing logic for outbound requests targeted out of our domain
# (keep in mind messages to our users can end up here too: for example,
#  an INVITE may be UsrLoc-ed, then the other party uses outbound
#  proxy with r-uri=the usr_loced addredd (typically IP))
route[2] {
        append_hf("P-hint: OUTBOUND\r\n");
        t_relay();
}

#------- ALIASED OUTBOUND --------------------------------------------
# routing logic for inbound requests aliased outbound; unlike
# with real outbound requests we do not force authentication
# as these calls are server by our server and we do not want
# to disqualify unathenticated request originatiors from other
# domains
route[5] {
        append_hf("P-hint: ALIASED-OUTBOUND\r\n");
        t_relay();
}






More information about the sr-users mailing list