Hello Experts,

I'm not an expert in Kamailio, but thanks to some excellent online resources, I 
managed to set up a basic interconnection between Teams and Kamailio.

So far, outbound calls, as well as blind and attended call transfers, are 
working smoothly. However, I'm facing a challenge with call disconnection for 
outbound calls. Specifically, when an outbound call is made and the called 
party hangs up, the BYE message isn't being relayed properly towards the Teams 
side.

In my routing configurations, I remove the Record-Route header received from 
Teams and add a new Record-Route header with Kamailio's IP before forwarding it 
to my IP PBX (FreeSwitch). For the BYE message to be processed correctly, 
Microsoft Teams requires the original contact in the Request URI (RURI) and the 
Route header to match the initial Record-Route included in the INVITE. 
Currently, my BYE message appears as follows:


BYE 
sip:api-du-a-auea.pstnhub.microsoft.com:443;x-i=5e96d703-b1e7-449c-aebf-a87bfa628176;x-c=f61b674bc597513ab8d888dbe7c560fb/d/8/9a6c508a9cbd44ebb892b62c33ba9b67
 SIP/2.0
Via: SIP/2.0/UDP 
x.x.x.x:5060;branch=z9hG4bKeab5.b657e3455b6d11ed6975c69882632a27.0
Via: SIP/2.0/UDP x.x.x.x;received=x.x.x.x;rport=5060;branch=z9hG4bKK3HKQBUvX42ya
Max-Forwards: 69
From: <sip:[email protected]:5061;user=phone>;tag=j5gptBSXXrXDc
To: "XYZ Pty Ltd" 
<sip:[email protected]:5061;user=phone>;tag=3a5f0c9e32bc4eb1bffed29dc954118f
Call-ID: f61b674bc597513ab8d888dbe7c560fb
CSeq: 80555743 BYE
User-Agent: Unknown/v1.0
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, 
REFER, NOTIFY
Supported: timer, path, replaces
Reason: MVTSLocal;cause=10;text="BYE received"
Content-Length: 0


Kamailio conducts a lookup for api-du-a-auea.pstnhub.microsoft.com but ends up 
sending the BYE message to an incorrect IP.

Below is a snippet of my routing block configurations:


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

        # per request initial checks
        route(REQINIT);

        #check who is the sender
        route(INITCHECK);

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

        # handle retransmissions
        if (!is_method("ACK")) {
                if(t_precheck_trans()) {
                        t_check_trans();
                        exit;
                }
                t_check_trans();
        }

        # handle requests within SIP dialogs
        route(WITHINDLG);

        ### only initial requests (no To tag)

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

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

        # update $du to set the destination address for proxying
        #$du = "sip:" + $rd + ":9";

        route(RELAY);
        exit;
}

route[INITCHECK] {
        if(from_uri =~ ".*microsoft.com")
        {
                setflag(FROM_TEAMS);
                $du = "sip:" + "MY_PBX_IP" + ":" + "5060";

                //added by SHK

                remove_hf("Record-Route"); // Remove existing Record-Route 
header
                append_hf("Record-Route: <sip:KAM_IP:5060;transport=udp>\r\n");

                route(HANDLE_RTP_FROM_TEAMS);
        }

        if(from_uri =~ ".*" + "MY_PBX_IP")
        {
                setflag(FROM_PBX);
                $du="sip:sip.pstnhub.microsoft.com;transport=tls";
                route(HANDLE_RTP_FROM_PBX);
        }
}

#Manage RTP & transcoding comming from Teams to PBX
route[HANDLE_RTP_FROM_TEAMS] {
        t_on_reply("PBX_REPLY_TO_TEAMS");

        if (has_body("application/sdp"))
        {
                rtpengine_manage("RTP codec-mask=all codec-transcode=PCMA 
replace-origin replace-session-connection ICE=remove media-address=HOST_IP");
               // record_route();
                t_relay_to_udp("MY_PBX_IP","5060");
        }
        else
        {
                rtpengine_manage();
        }
}

#Manage RTP & transcoding comming from PBX to Teams
route[HANDLE_RTP_FROM_PBX] {
        t_on_reply("TEAMS_REPLY_TO_PBX");

        if (has_body("application/sdp"))
        {
                rtpengine_manage("SRTP codec-mask=all ICE=force 
codec-transcode=PCMA replace-origin replace-session-connection 
media-address=ADVERTISE_IP");

                $rd = "sip.pstnhub.microsoft.com";
                $td = "kamsbc.xyzdomain.com";
                $fd = "kamsbc.xyzdomain.com";

               // record_route();

                #Set TLS SNI (server name & server id)
                $xavp(tls=>server_name) = "kamsbc.xyzdomain.com";
                $xavp(tls=>server_id) = "kamsbc.xyzdomain.com";

                t_relay();
        }
        else
        {
                rtpengine_manage();
        }
}


# Wrapper for relaying requests
route[RELAY] {

        # 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] {
        if($ua =~ "friendly-scanner|sipcli|VaxSIPUserAgent") {
                # silent drop for scanners - uncomment next line if want to 
reply
                # sl_send_reply("200", "OK");
                exit;
        }

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

        if(is_method("OPTIONS")) {
                sl_send_reply("200","Keepalive");
                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()) return;

        #Teams reINVITEs
        if(isflagset(FROM_TEAMS)) {
                loose_route();
                t_relay();
                exit;
        }

        if(isflagset(FROM_PBX)) {
                #Set TLS SNI (server name & server id)
                $xavp(tls=>server_name) = "kamsbc.xyzdomain.com";
                $xavp(tls=>server_id) = "kamsbc.xyzdomain.com";

                loose_route();
                t_relay();
                exit;
        }


        # 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

                        #set coresponding cert on transactions
                        if($fd == "kamsbc.xyzdomain.com") {
                                $xavp(tls=>server_name) = 
"kamsbc.xyzdomain.com";
                                $xavp(tls=>server_id) = "kamsbc.xyzdomain.com";
                        }

                } else if ( is_method("NOTIFY") ) {
                        # Add Record-Route for in-dialog NOTIFY as per RFC 6665.
                        record_route();
                }
                route(RELAY);
                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;
}

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

# Manage incoming replies
onreply_route[MANAGE_REPLY] {
        xdbg("incoming reply\n");
}

#PBX On Reply
onreply_route[PBX_REPLY_TO_TEAMS]
{

        if (has_body("application/sdp"))
        {
                rtpengine_manage("SRTP codec-mask=all codec-transcode=PCMA 
replace-origin replace-session-connection media-address=ADVERTISE_IP");
        }
        else
        {
                rtpengine_manage();
        }

//added by SHK

       if (status == "200" && method == "INVITE") {
        remove_hf("Contact"); # Remove existing Contact header
        append_hf("Contact: <sip:kamsbc.xyzdomain.com:5061;transport=tls>\r\n");
    }


       if (status=="200")
       {
        remove_hf("ALLOW:");
        append_hf("ALLOW: INVITE,ACK,OPTIONS,CANCEL,BYE,NOTIFY 
\r\n","CONTENT-TYPE");

        }

}


#From Teams On Reply
onreply_route[TEAMS_REPLY_TO_PBX]
{
        if (has_body("application/sdp"))
        {
                rtpengine_manage("RTP codec-mask=all codec-transcode=PCMA 
replace-origin replace-session-connection media-address=HOST_IP");
        }
        else
        {
                rtpengine_manage();
        }


}

# Manage failure routing cases
failure_route[MANAGE_FAILURE] {
        if (t_is_canceled()) exit;
}

event_route[tm:local-request] {
        if(is_method("OPTIONS") && $ru =~ "pstnhub.microsoft.com") {
                append_hf("Contact: 
<sip:kamsbc.xyzdomain.com:SBC_PORT;transport=tls>\r\n");
        }
        xlog("L_INFO", "Sent out tm request: $mb\n");
}


####### Routing Logic End ########


Given these details, I suspect the issue might be related to how I'm handling 
the Record-Route headers or potentially a misconfiguration in directing the BYE 
message. I would greatly appreciate any insights, suggestions, or guidance on 
how to correctly relay the BYE message back to Teams, or further refine my 
existing configuration.

Thank you in advance for your help and support!



Regards,
Shah Hussain
__________________________________________________________
Kamailio - Users Mailing List - Non Commercial Discussions
To unsubscribe send an email to [email protected]
Important: keep the mailing list in the recipients, do not reply only to the 
sender!
Edit mailing list options or unsubscribe:

Reply via email to