pyVoIP icon indicating copy to clipboard operation
pyVoIP copied to clipboard

Sending BYE should target caller

Open Input-BDF opened this issue 3 years ago • 6 comments

BYE Message should be target caller directly not server. Example but unclean implementation on SIP.bye() to mitigate issue

def bye(self, request):
        target = None
        #assuming this only comes out of active calls
        session_origin = request.body['o']['address']
        for v in request.headers['Via']:
            if v['address'][0] == session_origin:
                target, port = v['address']
        message = self.genBye(request)
        if target != None:
            #send directly to client
            self.out.sendto(message.encode('utf8'), (target, int(port)))
        else:
            #send directly to server
            self.out.sendto(message.encode('utf8'), (self.server, self.port))

Needs investigation. Not shure right now about correct behaviour.

Input-BDF avatar Feb 01 '22 13:02 Input-BDF

I've not come across this before anywhere in the RFCs, do you know the RFC and section that references that it SHOULD go to the other client and not the server?

I do know that some servers try to hand off connections once they've been established by the server through what I believe to be called "bridging" though that may just be Asterisk's term for it. I personally have bridging disabled by default, though I did attempt to make pyVoIP be capable of it, which is where renegotiation comes from.

Personally, I lean more towards sending the BYE request to the server by default and to the client as a backup, but then the feature would essentially never be used.

At the end of the day, I'd like to read the RFCs Section on the topic before I come to any decision.

tayler6000 avatar Feb 02 '22 05:02 tayler6000

At the end of the call, Bob disconnects (hangs up) first and generates a BYE message. This BYE is routed directly to Alice's softphone, again bypassing the proxies. Alice confirms receipt of the BYE with a 200 (OK) response, which terminates the session and the BYE transaction. Section 4 - Overview of Operation

I my current usecase the server does not react on BYE so session stays open for the targeted UA.

If bridging "bypasses" this we should inspect this via WireShark (as I stumbled about this issue) and/or find out what happens if BYE goes directly anyhow. Maybe the server doesn't care. If indirect BYEs are mandatory in some servermodes it shouldn be to complicated to implement this way of behaviour via some config parameter (e.g. self.bridgedmode Values [True, False], or self.servermode Values: [....,....,...])

Input-BDF avatar Feb 02 '22 10:02 Input-BDF

After reading this section, it states:

In this case, the 200 (OK) is routed back through the two proxies and is received by Alice's softphone, which then stops the ringback tone and indicates that the call has been answered. Finally, Alice's softphone sends an acknowledgment message, ACK, to Bob's SIP phone to confirm the reception of the final response (200 (OK)). In this example, the ACK is sent directly from Alice's softphone to Bob's SIP phone, bypassing the two proxies. This occurs because the endpoints have learned each other's address from the Contact header fields through the INVITE/200 (OK) exchange, which was not known when the initial INVITE was sent.

So basically the 200 OK should be sent to whatever the first VIA header was. At this point, the caller sends an ACK directly to the Contact listed on the 200 OK. And at that point, all communications go between those two devices directly. I've never come across this issue personally because of my use case. This section talks about a softphone calling another phone through a proxy. pyVoIP was designed with Asterisk which is a PBX, not a proxy server. I still need to run Wireshark on a call to be sure, but I'm guessing I've never run into this issue because I essentially establish a call with the PBX, and the PBX then establishes a call with the recipient. Then the PBX either attempts to bridge the calls (which would basically simulate this section) or it just continues to pass along messages, which is how my PBX is configured.

I'll post an update on here when I have it.

tayler6000 avatar Feb 02 '22 21:02 tayler6000

ACK (F12), BYE (F13) and OK (F14) in the diagram go directly, cause the clients now should know each other.

Actually if you have multiple VIA-Headers the first VIA-Header can be the caller. But also the Server^^. Taking the last VIA would more reliable but: Why we dont take the Contact header as it is designed for the INVITE/ Call usecase:

The Contact header field MUST be present and contain exactly one SIP
   or SIPS URI in any request that can result in the establishment of a
   dialog.  For the methods defined in this specification, that includes
   only the INVITE request.  For these requests, the scope of the
   Contact is global.  That is, the Contact header field value contains
   the URI at which the UA would like to receive requests, and this URI
   MUST be valid even if used in subsequent requests outside of any
   dialogs.

Contact: <sip:client2@[CALLERIP];gr=80051077-4A83-EC11-A926-1B36E2864162>

In my code example on issue creation I totally forgot about contact header and thought it's an idea to take the o= attribute as origin, cause it's the origin of the media session. And I was a little bit under pressure with my project^^

The wired things I also just realized: Call: Softphone1 > Softphone2 and Softphone1 hangs up send BYE via Server. Call: Softphone1 > pyVoip and Softphone1 hangs up sends BYE directly towards pYoIP.

So there is somewher something different I havn't found yet.

I belive I also have to setup an Asterisk parallel to my Kamailio Instance. So I can also check the behaviour there and we are on the same level.

Input-BDF avatar Feb 03 '22 11:02 Input-BDF

K. Think I found some "magic" for the moment by analyzing sended packets.

If the OK message to an INVITE goes out as in current implementation: Bye, Ack,.. should be Client2Client

If you add regRequest += "Record-Route: <sip:[SERVERIP];lr>\n" to pyVoIPS OK in SIPClient.genAnswer() it seams to establish a routing via the server or tells him to route. At least so far for the one direction. There is more. Cause this way again I ran into the issue sending BYE from pyVoip to the server to hangup and clear the call the Server returns 404 Not Found.

So what to do: add byeRequest += "Route: <sip:{SERVERIP];lr>\n" to SIPClient.genBye() and you can also do this part of communication via the server.

If I don't miss anything else. There are three Options:

  • doing this stuff all they way Client2Client -> adjusting pyVoIPs SIP.bye() to target other client instead of server using contact header
  • doing it Client2Server -> adjusting genOK and genBye with the above route lines and leave SIP.bye() as is
  • make it configurable to let the user decide what to do and take advantage out of both or find out how to automate selection of desired behaviour

Input-BDF avatar Feb 03 '22 12:02 Input-BDF

This should be fixed, but I want to make sure this process is correct in pyVoIP before we release 2.0.0.

tayler6000 avatar May 09 '23 02:05 tayler6000