c++ - 如何使用 PJSIP 库解码 SIP 字节流?

标签 c++ sip decode pjsip

我正在尝试使用 pjsip库来解码以下 SIP 字节流,但出现段错误。我的代码有什么问题?

#include <pjsip.h>

int main()
{

    char __MSG[] = {
        0x49, 0x4e, 0x56, 0x49, 0x54, 0x45, 0x20, 0x73, 0x69, 0x70,
        0x3a, 0x40, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
        0x31, 0x20, 0x53, 0x49, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d,
        0x0a, 0x54, 0x6f, 0x3a, 0x20, 0x3c, 0x73, 0x69, 0x70, 0x3a,
        0x31, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2e, 0x34, 0x35, 0x3e,
        0x0d, 0x0a, 0x56, 0x69, 0x61, 0x3a, 0x20, 0x53, 0x49, 0x50,
        0x2f, 0x32, 0x2e, 0x30, 0x2f, 0x55, 0x44, 0x50, 0x20, 0x31,
        0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2e, 0x34, 0x35, 0x0d, 0x0a,
        0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, 0x22, 0x74, 0x65, 0x73,
        0x74, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3c, 0x73, 0x69, 0x70,
        0x3a, 0x31, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x39,
        0x39, 0x3e, 0x0d, 0x0a, 0x43, 0x61, 0x6c, 0x6c, 0x2d, 0x49,
        0x44, 0x3a, 0x20, 0x31, 0x34, 0x38, 0x31, 0x30, 0x2e, 0x30,
        0x2e, 0x31, 0x2e, 0x34, 0x35, 0x0d, 0x0a, 0x43, 0x53, 0x65,
        0x71, 0x3a, 0x20, 0x31, 0x20, 0x49, 0x4e, 0x56, 0x49, 0x54,
        0x45, 0x0d, 0x0a, 0x4d, 0x61, 0x78, 0x2d, 0x46, 0x6f, 0x72,
        0x77, 0x61, 0x72, 0x64, 0x73, 0x3a, 0x20, 0x32, 0x30, 0x0d,
        0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x3a, 0x20,
        0x3c, 0x73, 0x69, 0x70, 0x3a, 0x31, 0x32, 0x37, 0x2e, 0x30,
        0x2e, 0x30, 0x2e, 0x31, 0x3e, 0x0d, 0x0a, 0x0d, 0x0a, NULL
    };



    char *testmsg = __MSG;

    pj_size_t msgsize;
    pj_status_t status;


    // INIT
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    status = pjlib_util_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    // PARSING
    pj_caching_pool cp;
    pj_caching_pool_init(&cp, NULL, 1024*1024);
    pj_pool_t *pool = pj_pool_create(&cp.factory, "parser_pool", 4000, 4000, NULL);
    pjsip_parser_err_report err;

    int len = strlen(testmsg);
    pjsip_msg *msg = pjsip_parse_msg(pool, __MSG, len, &err);

    printf("The end...");

    return 0;
}

Program terminated with signal 11, Segmentation fault.
#0 0x0805befb in pj_scan_peek () (gdb) bt
#0 0x0805befb in pj_scan_peek ()
#1 0x080507f6 in int_parse_msg ()
#2 0x080523a2 in pjsip_parse_msg ()
#3 0x0804fa89 in main () (gdb)

最佳答案

您需要使用 SIP 端点实例。来自doc :

SIP Endpoint instance (pjsip_endpoint) can be viewed as the master/owner of all SIP objects in an application. It performs the following roles:

  • it manages the allocation/deallocation of memory pools for all objects.
  • it manages listeners and transports, and how they are used by transactions.
  • it receives incoming messages from transport layer and automatically dispatches them to the correct transaction (or create a new one).
  • it has a single instance of timer management (timer heap).
  • it manages modules, which is the primary means of extending the library.
  • it provides single polling function for all objects and distributes events.
  • it automatically handles incoming requests which can not be handled by existing modules (such as when incoming request has unsupported method).
  • and so on..

Application should only instantiate one SIP endpoint instance for every process.

您需要调用 pjsip_endpt_create创建端点。

看看Stateless SIP Endpoint示例以了解初始化和设置端点所需的库调用的一般结构。

其他注意事项:

  • pjsip_parse_msg 函数将 pjsip_parser_err_report 列表作为最后一个参数。您必须使用 pj_list_init(&err) 初始化列表。
  • 确保在调用 pj_pool_create 后检查池不为 NULL。
  • 文档没有说明不将 NULL 池工厂策略传递给 pj_caching_pool_init 是否可以;最好只传递默认值(如下例所示)。

我相信它应该看起来像这样(但还没有测试过):

    // INIT
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    status = pjlib_util_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    // Create pool factory (for memory allocations)
    pj_caching_pool cp;
    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 1024*1024);

    // Create global endpoint
    static pjsip_endpoint *sip_endpt;
    status = pjsip_endpt_create(&cp.factory, "uniquesipendpointname", &sip_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    // PARSING    
    pj_pool_t *pool = pj_pool_create(&cp.factory, "parser_pool", 4000, 4000, NULL);
    pjsip_parser_err_report err;

    int len = strlen(testmsg);
    pj_list_init(&err);
    pjsip_msg *msg = pjsip_parse_msg(pool, __MSG, len, &err);

关于c++ - 如何使用 PJSIP 库解码 SIP 字节流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18864684/

相关文章:

c++ - CppCMS-嵌入式 404

java - 如何使用 Hadoop Mapreduce 运行非 Java 程序(首选 C++/Matlab)

c++ - 如何在 C++/CX 类之间传递旧版 C++ void 指针?

用于 Cordova 的 Java SIP 插件或用于音频和视频流的 Phonegap

android - Pjsua-2 Android-如何在调用电话时将自定义 header 添加到 INVITE 请求?

html - 在android中解码HTML实体

json - 在 shell 脚本中解码 JSON 和 base64 编码值

c++ - 我可以通过 WiX 的自定义操作访问 .wxl 本地化文件中的字符串吗?

android - Google SipDemo 应用程序未连接 UDP

windows - 在 perl 脚本中或与 perl 脚本一起使用 utf8