首页 > 解决方案 > python中的pjsua make_call隐私和自定义标头

问题描述

我正在尝试根据https://www.rfc-editor.org/rfc/rfc3325#section-9.3将“隐私:id”标头添加到拨出电话中

我有一个基于文档的简单调用脚本,它可以进行调用,但是当我用 tcpdump 查看它并且调用者 ID 没有被隐藏时,它不会添加标题。

较早的文档说 make_call 中的 hdr_list 应该是一个逗号分隔的扁平字符串中的标题键/值对列表。当我尝试传递 python 列表时,调用失败,所以我假设平面字符串是正确的,但它没有被传递——即使在我的测试中我只使用单个标头键/值对。

import sys
import pjsua as pj

SOUND_DEVICE = 0

# Logging callback
def log_cb(level, str, len):
    print str,

# Callback to receive events from Call
class MyCallCallback(pj.CallCallback):
    def __init__(self, call=None):
        pj.CallCallback.__init__(self, call)

    # Notification when call state has changed
    def on_state(self):
        print "Call is ", self.call.info().state_text,
        print "last code =", self.call.info().last_code,
        print "(" + self.call.info().last_reason + ")"

    # Notification when call's media state has changed.
    def on_media_state(self):
        global lib
        if self.call.info().media_state == pj.MediaState.ACTIVE:
            # Connect the call to sound device
            call_slot = self.call.info().conf_slot
            lib.conf_connect(call_slot, SOUND_DEVICE)
            lib.conf_connect(SOUND_DEVICE, call_slot)
            print "Hello world, I can talk!"

try:
    # Create library instance
    lib = pj.Lib()

    # Init library with default config
    lib.init(log_cfg = pj.LogConfig(level=3, callback=log_cb))

    # no soundcard
    lib.set_null_snd_dev()

    # Create UDP transport which listens to any available port
    transport = lib.create_transport(pj.TransportType.UDP)

    # Start the library
    lib.start()

    # Create local/user-less account

    acconf = pj.AccountConfig(domain="myendpoint.com", \
                           username="my_call_id", \
                           password="", \
                           proxy="", \
                           registrar="")

    acc = lib.create_account(acconf, cb=None)

    # Make call
    call = acc.make_call("sip:my_mobile@myendpoint.com", cb = MyCallCallback(),  hdr_list = "Privacy: id")


    # Wait for ENTER before quitting
    print "Press <ENTER> to quit"
    input = sys.stdin.readline().rstrip("\r\n")

    # We're done, shutdown the library
    lib.destroy()
    lib = None

except pj.Error, e:
    print "Exception: " + str(e)
    lib.destroy()
    lib = None
    sys.exit(1)

如何使用 Python 接口添加此标头?如果可以避免的话,我并不热衷于修改库代码。

版本信息: os_core_unix.c !pjlib 2.11 用于 POSIX 已初始化;pjsua_core.c .pjsua 版本 2.11 for Linux-4.15.0.97/x86_64/glibc-2.27 已初始化

标签: pythonpjsippjsua2

解决方案


函数文档https://www.pjsip.org/python/pjsua.htm#Account 具有误导性 make_call(self, dst_uri, cb=None, hdr_list=None)

hdr_list -- 与传出邀请一起发送的可选标头列表

基于这一点会认为需要传递的是 ["Privacy: id", "My-other-header-key: value"]

事实上,一旦阅读了 C 库代码,就会发现需要一个元组列表:

https://github.com/pjsip/pjproject/blob/ea7105c222d657d3c1f7fb18ff9130450e2e40e6/pjsip-apps/src/py_pjsua/py_pjsua.c#L458

    if (PyList_Check(py_hdr_list)) {
    int i;

        for (i = 0; i < PyList_Size(py_hdr_list); i++) 
    { 
            pj_str_t hname, hvalue;
        pjsip_generic_string_hdr * new_hdr;
            PyObject * tuple = PyList_GetItem(py_hdr_list, i);

因此 python 包装器应该传递: [("Privacy","id"), ("My-other-header-key", "value")]

为 make_call 方法生成 hdr_list 参数的示例帮助函数:

def fill_hdrs(number, domain):
   l = list()
   l.append(('P-Asserted-Identity','<sip:%s@%s>' % (number, domain)))
   l.append(('Privacy','id'))
   return(l)

推荐阅读