pythonsippjsippjsua2

PJSIP Get arbitrary SIP header from incoming call


I am using PJSIP and PJSUA2+Python to implement a custom softphone for our agents. Right now, we are doing custom call display based on regex matches of the incoming caller-id number.

This is a bit ugly as the we prepend _20, _21, _22, etc onto the caller-id number, just to have it detected and stripped off by the softphone. The downside is that it makes our CDR reports uglier and those prefixes show up if any other software is used to interact with our SIP server.

We have control of the SIP server, so we would like to place that information in a custom X-Queue-Info SIP header for the incoming call. As it stands, I cannot find anywhere in PJSUA+Python to grab a list of call headers, or extract a single header. I know this functionality exists in the underlying PJSIP library, but it does not seem to be exposed in PJSUA2.

Is there an "easy" way to go about this that I'm missing. As far as I can tell, my only option is to build a custom version of pjsua that exposes that API. I do not have a lot of C experience and have never customized a Python C extension before, so was wondering if I'm simply missing something in the existing API?


Solution

  • I'm probably late to the party, but I had the same question and also couldn't find a good answer. I found this solution browsing the pjsua2 source:

    The Account class has the onIncomingCall callback which takes OnIncomingCallParam as an argument: https://github.com/pjsip/pjproject/blob/450baca94f475345542c6953832650c390889202/pjsip/include/pjsua2/account.hpp#L1426

    The OnIncomingCallParam structure contains SipRxData instance under the rdata attribute: https://github.com/pjsip/pjproject/blob/450baca94f475345542c6953832650c390889202/pjsip/include/pjsua2/siptypes.hpp#L468

    From there you can read the whole SIP message as string (wholeMsg attribute):

    class MyAccount(Account):
        ...
    
        def onIncomingCall(self, prm: pj.OnIncomingCallParam) -> None:  # pylint: disable=C0103
            """On incoming call callback. When there is an incoming call, this function is called."""
            sip_message: str = prm.rdata.wholeMsg
            sip_message_lines: List[str] = sip_message.split("\r\n")
            for line in sip_message_lines:
                log.debug(f"SIP message: {line}")