Hi all, Another attempt,

After doing some tests, I saw that one of the problems was that was necessary to comment the following lines within the deffinition of the RELAY route:

# enable additional event routes for forwarded requests
    # - serial forking, RTP relaying handling, a.s.o.
    #if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
    #    if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
    #}


    At this time, all the features of my old configuration are working fine, and I can make good calls beetween standard SIP UA's and JSSIP UA's, originationg the call from both sides. I'm Using  Cisco SPA3000 GW, and Twinkle and SJ Phone softphones.

    But now, problems are still present with calls between JS SIP UA's. When the B side accepts the calls, Kamailio sends OK to A side, but Offering RTP/AVP instead of RTP/SAVFP, and the call is been rejected because of BAD Media Description.

Can anybody help me with this issue, please?. Here you are a snippet of my config, wich is based in the standard one, mixed with the example of Carlos Ruiz Diaz:





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


# Main SIP request routing logic
# - processing of any incoming SIP request starts with this route
# - note: this is the same as route { ... }
request_route {

    #!ifdef WITH_WEBSOCKETS
    if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
        && !(proto == WS || proto == WSS)) || $Rp == MY_MSRP_PORT) {
        xlog("L_WARN", "SIP request received on $Rp\n");
        sl_send_reply("403", "Forbidden");
        exit;
    }
    #!endif

    # per request initial checks
    route(REQINIT);

    #!ifdef WITH_WEBSOCKETS
    if (nat_uac_test(64)) {
    # Do NAT traversal stuff for requests from a WebSocket
    # connection - even if it is not behind a NAT!
    # This won't be needed in the future if Kamailio and the
    # WebSocket client support Outbound and Path.
    force_rport();
    if (is_method("REGISTER")) {
    fix_nated_register();
    } else {
    if (!add_contact_alias()) {
    xlog("L_ERR", "Error aliasing contact <$ct>\n");
    sl_send_reply("400", "Bad Request");
    exit;
    }
    }
    }
    #!endif
   

    # NAT detection
    route(NATDETECT);


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

    # handle requests within SIP dialogs
    route(WITHINDLG);
   

    ### only initial requests (no To tag)

    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
    #!ifdef WITH_CPL
    if(!cpl_run_script("incoming","is_stateful"))
                {
                        # script execution failed
                        t_reply("500","CPL script execution failed");
                 };
    #!endif

    }

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

    #if (!is_method("INVITE")) {
    #route(RELAY);
    #exit;
    #}

   
    if (!is_method("INVITE")) {
    route(RELAY);
    exit;
    }

    # user location service
    route(LOCATION);
}

#!ifdef WITH_WEBRTCGW
route[SETUP_BY_TRANSPORT] {


if ($ru =~ "transport=ws") {
xlog("L_INFO", "Request going to WS");
rtpproxy_manage("froc+SP");
t_on_reply("REPLY_FROM_WS");

}
else if ($proto =~ "ws") {
xlog("L_INFO", "Request coming from WS");
rtpproxy_manage("froc-sp");
t_on_reply("REPLY_TO_WS");

}
else {
xlog("L_INFO", "This is a classic phone call");
rtpproxy_manage("co");
t_on_reply("MANAGE_CLASSIC_REPLY");
}
}

#!endif


route[RELAY] {

    #!ifdef WITH_WEBRTCGW
    route(SETUP_BY_TRANSPORT);
    #!endif


    # enable additional event routes for forwarded requests
    # - serial forking, RTP relaying handling, a.s.o.
    #if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
    #    if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
    #}
    if (is_method("INVITE|SUBSCRIBE|UPDATE")) {
        if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");
    }
    if (is_method("INVITE")) {
        if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
    }

    if (!t_relay()) {
        sl_reply_error();
    }
    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()) {

            #!ifdef WITH_WEBSOCKETS
            if ($du == "") {
            if (!handle_ruri_alias()) {
            xlog("L_ERR", "Bad alias <$ru>\n");
            sl_send_reply("400", "Bad Request");
            exit;
            }
            }
            #!endif
            route(DLGURI);
            if (is_method("BYE")) {
                setflag(FLT_ACC); # do accounting ...
                setflag(FLT_ACCFAILED); # ... even if the transaction fails
            }
            else if ( is_method("ACK") ) {
                # ACK is forwarded statelessy
                route(NATMANAGE);
            }
            else if ( is_method("NOTIFY") ) {
                # Add Record-Route for in-dialog NOTIFY as per RFC 6665.
                record_route();
            }
            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
                    route(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"))
    {
        #!ifdef WITH_CPL       
        cpl_process_register();
        #!endif
        if(isflagset(FLT_NATS))
        {
            setbflag(FLB_NATB);
            # uncomment next line to do SIP NAT pinging
            ## setbflag(FLB_NATSIPPING);
        }
        if (!save("location"))
            sl_reply_error();

        exit;
    }
}

# USER location service
route[LOCATION] {

#!ifdef WITH_SPEEDDIAL
    # search for short dialing - 2-digit extension
    if($rU=~"^[0-9][0-9]$")
        if(sd_lookup("speed_dial"))
            route(SIPOUT);
#!endif

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

    $avp(oexten) = $rU;
    if (!lookup("location")) {
        $var(rc) = $rc;
        route(TOVOICEMAIL);
        t_newtran();
        switch ($var(rc)) {
            case -1:
            case -3:
                send_reply("404", "Not Found");
                exit;
            case -2:
                send_reply("405", "Method Not Allowed");
                exit;
        }
    }

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

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

    if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") {
        route(TOVOICEMAIL);
        # returns here if no voicemail server is configured
        sl_send_reply("404", "No voicemail service");
        exit;
    }

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

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

    if (is_method("REGISTER") || from_uri==myself)
    {
        # authenticate requests
        if (!auth_check("$fd", "subscriber", "1")) {
            auth_challenge("$fd", "0");
            exit;
        }
        # user authenticated - remove auth header
        if(!is_method("REGISTER|PUBLISH"))
            consume_credentials();
    }
    # if caller is not local subscriber, then check if it calls
    # a local destination, otherwise deny, not an open relay here
    if (from_uri!=myself && uri!=myself)
    {
        sl_send_reply("403","Not relaying");
        exit;
    }

#!endif
    return;
}

# Caller NAT detection route
route[NATDETECT] {
#!ifdef WITH_NAT
    force_rport();
    if (nat_uac_test("19")) {
        if (is_method("REGISTER")) {
            fix_nated_register();
        } else {
            if(is_first_hop())
                set_contact_alias();
           
        }
        setflag(FLT_NATS);
    }
#!endif
    return;
}

# RTPProxy control
route[NATMANAGE] {
#!ifdef WITH_NAT
    if (is_request()) {
        if(has_totag()) {
            if(check_route_param("nat=yes")) {
                setbflag(FLB_NATB);
            }
        }
    }
    if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))
        return;

    #rtpproxy_manage("co");

    if (is_request()) {
        if (!has_totag()) {
            if(t_is_branch_route()) {
                add_rr_param(";nat=yes");
            }
        }
    }
    if (is_reply()) {
        if(isbflagset(FLB_NATB)) {
            if(is_first_hop())
                set_contact_alias();
                #add_contact_alias();
        }
    }
#!endif
    return;
}

# URI update for dialog requests
route[DLGURI] {
#!ifdef WITH_NAT
    if(!isdsturiset()) {
        handle_ruri_alias();
    }
#!endif
    return;
}

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

# 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

# route to voicemail server
route[TOVOICEMAIL] {
#!ifdef WITH_VOICEMAIL
    if(!is_method("INVITE|SUBSCRIBE"))
        return;

    # check if VoiceMail server IP is defined
    if (strempty($sel(cfg_get.voicemail.srv_ip))) {
        xlog("SCRIPT: VoiceMail rotuing enabled but IP not defined\n");
        return;
    }
    if(is_method("INVITE")) {
        if($avp(oexten)==$null)
            return;
        $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)
                + ":" + $sel(cfg_get.voicemail.srv_port);
    } else {
        if($rU==$null)
            return;
        $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip)
                + ":" + $sel(cfg_get.voicemail.srv_port);
    }
    route(RELAY);
    exit;
#!endif

    return;
}

# manage outgoing branches
branch_route[MANAGE_BRANCH] {
    xdbg("new branch [$T_branch_idx] to $ru\n");
    route(NATMANAGE);
}

# manage incoming replies
onreply_route[MANAGE_REPLY] {
    xdbg("incoming reply\n");
    if(status=~"[12][0-9][0-9]")
        route(NATMANAGE);
}

# manage failure routing cases
failure_route[MANAGE_FAILURE] {
    route(NATMANAGE);

    if (t_is_canceled()) {
        exit;
    }

#!ifdef WITH_BLOCK3XX
    # block call redirect based on 3xx replies.
    if (t_check_status("3[0-9][0-9]")) {
        t_reply("404","Not found");
        exit;
    }
#!endif

#################################################
#Desvío a buzón de voz si ocupado o no contesta

if (t_check_status("486|408")) {
        remove_hf("P-App-Name");
        append_hf("P-App-Name: voicemail\r\n");
        $var(usr_voicemail) = "voicemail" + $rU;
        append_hf("P-App-Param: mod=box;usr=$var(usr_voicemail);dom=sipproxy.a.com;uid=$var(usr_voicemail);did=sipproxy.a.com;\r\n");
         $ru = "sip:" + $var(usr_voicemail) + "@" + "192.168.0.197:5080";
        $du = $null;
        route(RELAY);
        exit;
    }
#################################################


#!ifdef WITH_VOICEMAIL
    # serial forking
    # - route to voicemail on busy or no answer (timeout)
    if (t_check_status("486|408")) {
        $du = $null;
        route(TOVOICEMAIL);
        exit;
    }
#!endif

}

#!ifdef WITH_WEBSOCKETS
onreply_route {
if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
&& !(proto == WS || proto == WSS)) || $Rp == MY_MSRP_PORT) {
xlog("L_WARN", "SIP response received on $Rp\n");
drop;
exit;
}
 
if (nat_uac_test(64)) {
# Do NAT traversal stuff for replies to a WebSocket connection
# - even if it is not behind a NAT!
# This won't be needed in the future if Kamailio and the
# WebSocket client support Outbound and Path.
add_contact_alias();
}
}
 
event_route[xhttp:request] {
set_reply_close();
set_reply_no_connect();
if ($Rp != MY_WS_PORT
#!ifdef WITH_TLS
&& $Rp != MY_WSS_PORT
#!endif
) {
xlog("L_WARN", "HTTP request received on $Rp\n");
xhttp_reply("403", "Forbidden", "", "");
exit;
}
 
xlog("L_DBG", "HTTP Request Received\n");
 
if ($hdr(Upgrade)=~"websocket"
&& $hdr(Connection)=~"Upgrade"
&& $rm=~"GET") {
 
# Validate Host - make sure the client is using the correct
# alias for WebSockets
if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
xlog("L_WARN", "Bad host $hdr(Host)\n");
xhttp_reply("403", "Forbidden", "", "");
exit;
}
 
# Optional... validate Origin - make sure the client is from an
# authorised website. For example,
#
# if ($hdr(Origin) != "http://communicator.MY_DOMAIN"
# && $hdr(Origin) != "https://communicator.MY_DOMAIN") {
# xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");
# xhttp_reply("403", "Forbidden", "", "");
# exit;
# }
 
# Optional... perform HTTP authentication
 
# ws_handle_handshake() exits (no further configuration file
# processing of the request) when complete.
if (ws_handle_handshake())
{
# Optional... cache some information about the
# successful connection
exit;
}
}
 
xhttp_reply("404", "Not Found", "", "");
}
 
event_route[websocket:closed] {
xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");
}
#!endif


#!ifdef WITH_WEBRTCGW
onreply_route[REPLY_TO_WS] {

xlog("L_INFO", "Reply from softphone: $rs");

if (t_check_status("183")) {
change_reply_status("180", "Ringing");
remove_body();
exit;
}

if(!(status=~"[12][0-9][0-9]"))
return;

rtpproxy_manage("froc+SP");

route(NATMANAGE);
}

onreply_route[REPLY_FROM_WS] {

xlog("L_INFO", "Reply from webrtc client: $rs");

if(status=~"[12][0-9][0-9]") {
rtpproxy_manage("froc-sp");
route(NATMANAGE);
}
}

onreply_route[MANAGE_CLASSIC_REPLY] {
xlog("L_INFO", "Boring reply from softphone: $rs");

if(status=~"[12][0-9][0-9]") {
rtpproxy_manage("co");
route(NATMANAGE);
}
}




#!endif


2014-06-02 21:49 GMT+02:00 LAA <ornitorrinco7424@gmail.com>:


Apologize. Previous message was too long.
L.


El 02/06/2014 20:25, "LAA" <ornitorrinco7424@gmail.com> escribió:

Hi all,

Another guy strugling his mind trying to get a configuration to enable calls between WebRTC UA (JSSIP) to standard SIP UA (Twinkle or SjPhone) I've been working with the examples that were shared by Carlos Ruiz Diaz and Peter Dunkley (thanks to both).

http://www.slideshare.net/crocodilertc/webrtc-websockets
http://caruizdiaz.com/2014/02/26/webrtc-kamailio/

Kamailio is not running behind NAT. I'm using rtpproxy-ng module with Kamailio 4.1.3, and Rtpengine.

I share a link with my current configuration, wich is based in Peters example, with websocket support from websocket.cfg example.

-  Calls between SIP standard UA's are working OK. I have some endpoint behind nat.
-  Calls between JSIP UA's are working OK. So, websocket support is running.
-  Calls from JSIP and Twinkle are NOT WORKING OK. sip UA send's back a 488 response, and Kamailio send it back to JSSIP (Incompatible SDP).
-  Calls from Twinkle to Jsip are NOT WORKING OK: Kamailio sends an INVITE to JSIP, and it returns an error. And Kamailio sends 488 to Twinkle.


It seems as if Kamailio is not catching 488. I share a snippet of my config, and links to tcpdump captures:

https://www.dropbox.com/s/i7c9ty57oauujc4/fromws0.pcap
https://www.dropbox.com/s/rqtjwcbgg1foaoq/tows0.pcap

What am I missing?


Best regards.

Luis.