本系列文章旨在探讨国标GB28181协议设备端的开发过程。本文将聚焦于架构设计和设备注册,并详细介绍了设备端的程序架构设计、exosip库介绍和接口分类,以及GB28181设备端的注册流程和信令交互报文。通过阅读本文,读者将深入了解GB28181协议设备端的架构设计原则、exosip库的使用方法,以及设备的注册过程和信令交互的关键报文。
在GB28181协议设备端的开发中,良好的程序架构设计是保证系统稳定性和可扩展性的基础。我们可以考虑以下方面:
以下为开发GB28181协议设备端的程序框架:
eXosip是一个基于oSIP库的扩展库,用于实现SIP协议的开发。它提供了一个事件驱动的编程接口,用于处理SIP信令和实现SIP应用程序,广泛用于GB28181设备端的开发。它提供了丰富的接口和功能,可以简化开发过程。下面是eXosip的内部架构的概述:
eXosip库的内部架构充分利用了oSIP库提供的底层功能,并提供了更高级别的接口和事件驱动的编程模型,使开发者能够更方便地实现基于SIP的应用程序。
exosip库的接口可以分为以下几类:
在使用exosip库前,需要进行初始化和配置的操作。具体步骤如下:
#include <osip2/osip.h>
#include <eXosip2/eXosip.h>
// 初始化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;
注册流程描述如下:
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: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip:34020000001110000002@192.168.1.54:10561>
Call-ID: 2847584547
CSeq: 1 REGISTER
Contact: <sip:34020000001110000002@192.168.1.54:10561;line=00c3a618be4c249>
Max-Forwards: 70
User-Agent: HbsGBSIP-1.0
Expires: 3600
Content-Length: 0
2 GB28181平台返回401错误:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK639602844
From: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip: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
3 加上鉴权信息后第二次发送注册报文:
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: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip:34020000001110000002@192.168.1.54:10561>
Call-ID: 2847584547
CSeq: 0 REGISTER
Contact: <sip: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
4 GB28181平台返回200注册成功:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK2311457380
From: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip:34020000001110000002@192.168.1.54:10561>;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);
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。