Как декодировать поток байтов SIP с помощью библиотеки 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;
}

Программа завершена с сигналом 11, Ошибка сегментации.
#0 0x0805befb в pj_scan_peek() (gdb) bt
#0 0x0805befb в pj_scan_peek()
#1 0x080507f6 в int_parse_msg()
#2 0x080523a2 в pjsip_parse_msg()
#3 0x0804fa89 в main() (gdb)


person B Faley    schedule 18.09.2013    source источник


Ответы (1)


Вам необходимо использовать экземпляр конечной точки SIP. Из документа:

Экземпляр конечной точки SIP (pjsip_endpoint) можно рассматривать как главный/владелец всех объектов SIP в приложении. Он выполняет следующие роли:

  • он управляет выделением/освобождением пулов памяти для всех объектов.
  • он управляет слушателями и транспортами, а также тем, как они используются транзакциями.
  • он получает входящие сообщения от транспортного уровня и автоматически отправляет их в нужную транзакцию (или создает новую).
  • он имеет единственный экземпляр управления таймером (куча таймера).
  • он управляет модулями, что является основным средством расширения библиотеки.
  • он обеспечивает единую функцию опроса для всех объектов и распределяет события.
  • он автоматически обрабатывает входящие запросы, которые не могут быть обработаны существующими модулями (например, когда входящий запрос имеет неподдерживаемый метод).
  • и так далее..

Приложение должно создавать только один экземпляр конечной точки SIP для каждого процесса.

Чтобы создать конечная точка.

Взгляните на пример Конечная точка SIP без сохранения состояния, чтобы получить представление об общих структура библиотечных вызовов, которые необходимо выполнить для инициализации и настройки конечной точки.

Другие пункты примечания:

  • Функция pjsip_parse_msg принимает список pjsip_parser_err_report в качестве последнего аргумента. Вы должны инициализировать список, используя pj_list_init(&err).
  • Убедитесь, что вы проверяете, что пул не равен NULL после вызова pj_pool_create.
  • В документе не указано, можно ли не передавать политику фабрики пула 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);
person Robert Groves    schedule 28.09.2013
comment
После выполнения последней строки msg равно NULL и не заполняется. Почему? - person B Faley; 29.09.2013
comment
Есть ли ошибки в переменной списка pjsip_parser_err_report err? Вам придется пройтись по этому списку, чтобы выяснить, были ли ошибки при анализе сообщения. - person Robert Groves; 30.09.2013
comment
Я смог разобрать это самое сообщение с помощью библиотеки osip, так что формат сообщения правильный. По-видимому, при разборе сообщения нет ошибки. exept_code установлено на 1379205, что должно быть неопределенным значением. - person B Faley; 30.09.2013