pyVoIP icon indicating copy to clipboard operation
pyVoIP copied to clipboard

BYE: 401 Unauthorized

Open emiltem opened this issue 3 years ago • 4 comments

Hi everyone!

I'm getting 401 Unauthorized error when trying to hang up, as a result, my python script exits but the call continues.

try:
    phone = VoIPPhone(domain, Port, user_name, Password, call_callback=answer)
    phone.start()
    call = phone.call(phone_number)

    while call.state == CallState.DIALING:
        print("Dailing...", end="\r")
        time.sleep(1)

    if call.state == CallState.ANSWERED:
        # Trying to hangup
        call.hangup()

    while call.state != CallState.ENDED:
        time.sleep(1)

    phone.stop()
except Exception as e:
    print(e)

I tried to add the Authorization header to the bye message (although, I'm not sure I do that properly) - still does not work. Can someone help with this?

emiltem avatar Oct 31 '22 19:10 emiltem

OK, I've found out how to fix that, I used the code from the feature/Add-TLS branch, but I'm sure the same things can be done on the code from the master branch:

  1. I've slightly changed the To inside the BYE message by adding a tag

So now I have the following gen_bye:

def gen_bye(self, request: SIPMessage) -> str:
    tag = self.tagLibrary[request.headers["Call-ID"]]
    c = request.headers["Contact"].strip("<").strip(">")
    byeRequest = f"BYE {c} SIP/2.0\r\n"
    byeRequest += self._gen_response_via_header(request)
    _from = request.headers["From"]
    fromH = f' "{_from["display-name"]}" <{_from["uri"]}>'
    to = request.headers["To"]
    toH = f' "{to["display-name"]}" <{to["uri"]}>'
    if request.headers["From"]["tag"] == tag:
        byeRequest += f"From: {fromH};tag={tag}\r\n"
        byeRequest += f"To: {to['raw']}"
        if 'tag' in to:
            # Added tag for To
            byeRequest += f";tag={to['tag']}"
        byeRequest += "\r\n"
    else:
        byeRequest += f"To: {_from['raw']}\r\n"
        byeRequest += f"From: {toH};tag={tag}\r\n"
    byeRequest += f"Call-ID: {request.headers['Call-ID']}\r\n"
    cseq = int(request.headers["CSeq"]["check"]) + 1
    byeRequest += f"CSeq: {cseq} BYE\r\n"
    byeRequest += (
        "Contact: "
        + f"<sip:{self.user}@{self.bind_ip}:{self.bind_port}>\r\n"
    )
    byeRequest += f"User-Agent: pyVoIP {pyVoIP.__version__}\r\n"
    byeRequest += f"Allow: {(', '.join(pyVoIP.SIPCompatibleMethods))}\r\n"
    byeRequest += "Content-Length: 0\r\n\r\n"

    return byeRequest

emiltem avatar Nov 01 '22 18:11 emiltem

Sometimes another problem is the contact field. You can get something like <sip:[email protected];gr=urn:uuid:7d0db4d2-57ce-00a1-a018-6d9143ab3d74>;+org.linphone.specs="ephemeral/1.1,groupchat/1.1,lime" and then the part
c = request.headers["Contact"].strip("<").strip(">") does not work. For myself I fix it with this small change c = request.headers['Contact'].split(">", 1)[0].strip('<')

xyc0815 avatar Nov 03 '22 19:11 xyc0815

I had the same issue in gen_ack, my fix is

# this one does not work
# t = request.headers["To"]["raw"].strip("<").strip(">")

[to, *rest] = request.headers["To"]["raw"].split(';')
t = ';'.join([to.strip("<").strip(">"), *rest])

ackMessage = f"ACK {t} SIP/2.0\r\n"
...

emiltem avatar Nov 03 '22 20:11 emiltem

I believe this is fixed in the development branch, but I'd like to confirm that.

tayler6000 avatar May 09 '23 02:05 tayler6000