• 国标GB28181协议客户端开发(二)程序架构和注册


    国标GB28181协议客户端开发(二)程序架构和注册

    本系列文章旨在探讨国标GB28181协议设备端的开发过程。本文将聚焦于架构设计和设备注册,并详细介绍了设备端的程序架构设计、exosip库介绍和接口分类,以及GB28181设备端的注册流程和信令交互报文。通过阅读本文,读者将深入了解GB28181协议设备端的架构设计原则、exosip库的使用方法,以及设备的注册过程和信令交互的关键报文。

    一、程序架构设计

    在GB28181协议设备端的开发中,良好的程序架构设计是保证系统稳定性和可扩展性的基础。我们可以考虑以下方面:

    1. 分层架构:将设备端的功能划分为不同的层次,如媒体层、控制层、存储层和网络层等,以实现模块化的开发和维护。

    2. 模块设计:根据功能需求,将设备端划分为不同的模块,如平台接入模块、媒体解析模块、编码模块、解码模块等。每个模块负责特定的功能,通过接口进行交互和通信。

    3. 数据结构设计:GB28181协议涉及到丰富的数据结构,如设备信息、媒体流、信令消息等。在设计数据结构时,需要考虑数据的组织和访问效率,以及与协议规范的兼容性。

    以下为开发GB28181协议设备端的程序框架:

    二、exosip库介绍和接口分类

    eXosip是一个基于oSIP库的扩展库,用于实现SIP协议的开发。它提供了一个事件驱动的编程接口,用于处理SIP信令和实现SIP应用程序,广泛用于GB28181设备端的开发。它提供了丰富的接口和功能,可以简化开发过程。下面是eXosip的内部架构的概述:

    1. SIP上下文(SIP Context):
      eXosip库使用SIP上下文来管理和处理SIP会话。每个SIP上下文都有一个唯一的ID,可以通过函数eXosip_malloc()创建上下文。应用程序可以创建多个上下文来处理不同的SIP会话。

    2. 事件循环(Event Loop):
      eXosip库通过事件循环机制处理接收到的SIP消息和事件。事件循环会持续监听网络套接字,等待SIP消息的到达或定时器事件的触发。当有事件发生时,eXosip库将生成相应的事件,并将其放入事件队列中等待处理。

    3. 事件处理器(Event Handler):
      eXosip库提供了一组事件处理器函数,用于处理各种类型的事件,如注册、呼叫邀请、消息收发等。应用程序可以根据需要注册相应的事件处理器函数,并在事件发生时执行自定义的逻辑。

    4. SIP消息处理器(SIP Message Handler):
      eXosip库提供了一组函数来处理SIP消息,包括解析和构建SIP请求和响应。它使用oSIP库的底层功能来处理SIP消息的解析和组装,并提供了更高级别的接口供应用程序使用。

    5. 网络通信:
      eXosip库使用底层的网络套接字进行SIP通信。它提供了与网络层交互的功能,如创建和绑定套接字、发送和接收SIP消息等。应用程序可以根据需要配置和管理网络通信相关的参数。

    eXosip库的内部架构充分利用了oSIP库提供的底层功能,并提供了更高级别的接口和事件驱动的编程模型,使开发者能够更方便地实现基于SIP的应用程序。

    exosip库的接口可以分为以下几类:

    1. 初始化和配置接口:包括库的初始化、设置SIP协议栈的参数、配置监听端口等。

    2. 注册和注销接口:用于设备的注册和注销操作,包括注册请求的发送和接收处理等。

    3. 信令交互接口:用于发送和接收SIP信令消息,如呼叫邀请、媒体流控制等。

    三、exosip初始化和消息循环

    在使用exosip库前,需要进行初始化和配置的操作。具体步骤如下:

    1. 初始化exosip库:调用初始化接口,初始化exosip库,并设置一些全局参数。

    2. 配置SIP协议栈:通过配置接口,设置SIP协议栈的相关参数,如IP地址、端口等。

    3. 创建SIP上下文:使用上下文接口,创建一个SIP上下文,用于后续的注册和信令交互操作。

    #include 
    #include 
    
    
    // 初始化eXosip和osip栈
    exosip_ = eXosip_malloc();
    ret_code = eXosip_init(exosip_);
    if (ret_code != OSIP_SUCCESS)
    {
       SIMPLE_LOG("Can't initialize eXosip!");
       exit(1);
    }
    
    // 配置exosip库参数,如IP地址和端口
    ret_code = eXosip_listen_addr(exosip_, IPPROTO_UDP, NULL, cfg_.sip_local_port, AF_INET, 0);
    if (ret_code != OSIP_SUCCESS)
    {
       SIMPLE_LOG("eXosip_listen_addr error!");
    
       eXosip_quit(exosip_);
    
       exit(1);
    }
    
    eXosip_set_user_agent(exosip_, "HbsGBSIP-1.0");
    
    // 发送初始注册报文
    SipSendRegister(false, nullptr);
    
    // 接收和处理SIP报文
    while (!is_need_stop_)
    {
       // 处理事件
       eXosip_event_t* sip_event = eXosip_event_wait(exosip_, 0, 10);
    
       // 一般处理401/407采用库默认处理
       eXosip_lock(exosip_);
       eXosip_default_action(exosip_, sip_event);
       eXosip_unlock(exosip_);
    
       // 超时
       if (sip_event == NULL)
       {
          continue;
       }
    
       // 尝试解析报文头部信息
       OSipMsgParser msg_parser;
       if (sip_event->request)
       {
          msg_parser.ParseHeader(sip_event->request);
       }
    
       switch (sip_event->type)
       {
          case EXOSIP_REGISTRATION_SUCCESS: {
             // 注册成功处理
             break;
          }
          case EXOSIP_REGISTRATION_FAILURE: {
             // 注册失败处理
             break;
          }
          case EXOSIP_MESSAGE_NEW: {
             // 收到新的SIP消息处理
             if (sip_event->request) {
                // 处理请求消息
                osip_message_t* request = sip_event->request;
                // 解析和处理请求消息
             } else if (sip_event->response) {
                // 处理响应消息
                osip_message_t* response = sip_event->response;
                // 解析和处理响应消息
             }
             break;
          }
          case EXOSIP_CALL_INVITE: {
             // 收到呼叫邀请处理
             // 解析和处理呼叫邀请消息
             break;
          }
          // 其他事件处理...
    
          default:
             break;
          }
    
       // 释放事件
       eXosip_event_free(sip_event);
    }
    
    
    // 清理exosip库资源
    eXosip_quit(exosip_);
    osip_free(exosip_);
    exosip_ = NULL;
    
    

    四、GB28181注册过程中的信令交互报文

    注册流程描述如下:

    1. SIP代理向SIP服务器发送 Register请求;

    2. SIP服务器向 SIP代理发送响应401,并在响应的消息头 WWW_Authenticate字段中给出
      适合SIP代理的认证体制和参数;

    3. SIP代理重新向SIP服务器发送 Register请求,在请求的 Authorization字段给出信任书,
      包含认证信息;

    4. SIP 服务器对请求进行验证,如果检查出 SIP 代理身份合法,向 SIP 代理发送成功响应
      200OK,如果身份不合法则发送拒绝服务应答。

    WireShark截包后可见:

    1. 第一次注册:
    REGISTER sip:34020000002000000001@192.168.1.54:5060 SIP/2.0
    Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK639602844
    From: ;tag=91827836
    To: 
    Call-ID: 2847584547
    CSeq: 1 REGISTER
    Contact: 
    Max-Forwards: 70
    User-Agent: HbsGBSIP-1.0
    Expires: 3600
    Content-Length: 0
    
    1. GB28181平台返回401错误:
    SIP/2.0 401 Unauthorized
    Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK639602844
    From: 34020000001110000002@192.168.1.54:10561>;tag=91827836
    To: 34020000001110000002@192.168.1.54:10561>;tag=1724123124
    Call-ID: 2847584547
    CSeq: 1 REGISTER
    WWW-Authenticate: Digest realm="34020000", nonce="awer23sdfj123123", opaque="c3a02f1ecb122d255c4ae2266129d044", algorithm=MD5
    User-Agent: General
    Content-Length: 0
    
    1. 加上鉴权信息后第二次发送注册报文:
    REGISTER sip:34020000002000000001@192.168.1.54:5060 SIP/2.0
    Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK2311457380
    From: 34020000001110000002@192.168.1.54:10561>;tag=91827836
    To: 34020000001110000002@192.168.1.54:10561>
    Call-ID: 2847584547
    CSeq: 0 REGISTER
    Contact: 34020000001110000002@192.168.1.54:10561;line=00c3a618be4c249>
    Authorization: Digest username="34020000001110000002", realm="34020000", nonce="awer23sdfj123123", uri="sip:34020000002000000001@192.168.1.54:5060", response="dc953f5c48a92517ff6542ef6cd97e20", algorithm=MD5, opaque="c3a02f1ecb122d255c4ae2266129d044"
    Max-Forwards: 70
    User-Agent: HbsGBSIP-1.0
    Expires: 3600
    Content-Length: 0
    
    1. GB28181平台返回200注册成功:
    SIP/2.0 200 OK
    Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK2311457380
    From: ;tag=91827836
    To: ;tag=31243r3412
    Call-ID: 2847584547
    CSeq: 0 REGISTER
    User-Agent: General
    Date: 2023-03-15T16:18:33
    Expires: 300
    Content-Length: 0
    

    调用eXosip进行注册的代码如下:

    osip_message_t* reg = nullptr;
    
    SIMPLE_LOG("new build register\n");
    
    std::string from_str = MakeSIPFromToStr(cfg_.sip_local_device_id,
       cfg_.sip_local_ip, cfg_.sip_local_port);
    std::string to_str = MakeSIPFromToStr(cfg_.sip_server_id,
          cfg_.sip_server_ip, cfg_.sip_server_port);
    
    register_id_ = eXosip_register_build_initial_register(exosip_,
       from_str.c_str(),   //"sip:34010000002000000001@127.0.0.1:7777",
       to_str.c_str(),     //"sip:34020000002000000001@127.0.0.1:5060",
       NULL, expire_val, ®);
    
    auto ret = eXosip_register_send_register(exosip_, register_id_, reg);
    

    合作请加WX:hbstream或企鹅:229375788。(转载请注明作者和出处)

    合作请加作者hbstream(http://haibindev.cnblogs.com),转载请注明作者和出处

  • 相关阅读:
    【Pytorch】深度学习之优化器
    测试开发路线大纲与总结
    【桥接设计模式详解】Java/JS/Go/Python/TS不同语言实现
    无法启动此程序,因为计算机中“找不到msvcp140.dll”的解决方法
    【Spring】——1、使用@Configuration和@Bean给容器中注册组件
    【网站项目】109网上手机商城
    2023年天津农学院专升本招生专业及报考专业限制范围的通知
    一幅长文细学Vue(七)——路由
    SuperMap iPortal 与独立代理服务的 session 共享通过redis配置实现
    STM32的IAP讲解
  • 原文地址:https://www.cnblogs.com/haibindev/p/17503269.html