mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
gb28181模块可用性增强
主要改动, 1. 支持作为GB/T 28181上级平台 2. 新的目录接口sip_query_devicelist (/api/v1/gb28181?action=sip_query_devicelist) 3. 各种异常和问题修复 4. 其他一些小改动 以上改动基于feature/rtc分支,因为需要网页用WebRTC来拉GB28181的监控流,gb28181分支代码有点老了。 下面的序号n是指第n个差异块("@@ -"之间的内容)。 srs_gb28181.html 1. 原页面上多加了一个端口号 2-4. 给摄像头加上名称显示 5. 查询目录去掉chid 6. 删除通道参数分解为id和chid 7. API端口固定为1985 srs_app_gb28181.cpp 1-4. 四处因为错误而退出GB28181媒体处理循环,修改为不退出 5. payload为空异常 6. 修正判断startcode越界一个字符导致内存写越界的问题 ps流有可能末尾是全零填充,而且越界的那个字符正好是0x01,这样会多出一个nalu(末尾的三个0x00和一个越界的0x01),后面写video_data内存越界(if (first_pos != pre_pos){块,此处size - pre_pos - 4为-1,uint32_t naluLen得到的值为0,video_data[pre_pos+3] = p[0];写越界)破坏了其他数据,后续video_stream析构出错程序异常退出。 7. 此处srs后来已修复 8. 更新ssrc为被叫返回的值 原代码只支持标准中的《点播域内设备媒体流SSRC处理方式》(设备注册上来),不支持《点播外域设备媒体流SSRC处理方式》(即作为上级平台)。 这是因为如果srs作为上级平台,ssrc不是自己生成的,而是下级平台生成的。 9. 删除通道参数分解为id和chid 10. notify_sip_unregister后delete_stream_channel无效 11. notify_sip_query_catalog清空内存中的设备列表 12. 新函数query_device_list srs_app_gb28181.hpp 1. update_rtmpmuxer_to_newssrc_by_id声明 2. 新函数get_gb28181_config_ptr和函数delete_stream_channel声明修改 3. 新函数query_device_list srs_app_gb28181_sip.cpp 1-4. 在调试界面给摄像头加上名称显示;新函数clear_device_list和新函数dumpItemList 5-6. 两处因为错误而退出GB28181信令处理循环,修改为不退出 7. 设备注册上来,不检查服务器ID匹不匹配(支持作为上级平台) 8. 收到一个目录上报消息,更新内存中的数据 9. 更新ssrc为被叫返回的值 10. 新函数query_device_list srs_app_gb28181_sip.hpp 1. 在调试界面给摄像头加上名称显示 2. 每个设备加上item_list,用于存储目录;新函数clear_device_list和新函数dumpItemList 3. 新函数clear_device_list srs_app_http_api.cpp 1. 删除通道参数分解为id和chid 2. 新的接口sip_query_devicelist,用于查询所有设备的目录 srs_sip_stack.cpp 1. GB2312转UTF-8类 2. 被叫返回的ssrc初始化 3. parse_xml声明修改 4. 对XML内容进行字符集检测和转换 5-7. parse_xml定义修改 8. SIP BODY里面也有可能有\r\n 9-10. 防止恶意SIP消息 by vicious sip prober 11-12. 新的XML解析目录代码 13. 获取被叫返回的ssrc srs_sip_stack.hpp 1. 依赖vector 2. 每个设备加上item_list,用于存储目录 3. 被叫返回的ssrc 4. parse_xml声明修改
This commit is contained in:
parent
fe65c7bf84
commit
ffae1720ec
8 changed files with 370 additions and 53 deletions
|
@ -68,6 +68,7 @@ std::string srs_get_sip_session_status_str(SrsGb28181SipSessionStatusType status
|
|||
SrsGb28181Device::SrsGb28181Device()
|
||||
{
|
||||
device_id = "";
|
||||
device_name = "";
|
||||
invite_status = SrsGb28181SipSessionUnkonw;
|
||||
invite_time = 0;
|
||||
device_status = "";
|
||||
|
@ -102,6 +103,8 @@ SrsGb28181SipSession::SrsGb28181SipSession(SrsGb28181SipService *c, SrsSipReques
|
|||
_fromlen = 0;
|
||||
_sip_cseq = 100;
|
||||
|
||||
item_list_sumnum = 0;
|
||||
|
||||
}
|
||||
|
||||
SrsGb28181SipSession::~SrsGb28181SipSession()
|
||||
|
@ -338,19 +341,42 @@ void SrsGb28181SipSession::update_device_list(std::map<std::string, std::string>
|
|||
if (_device_list.find(id) == _device_list.end()){
|
||||
SrsGb28181Device *device = new SrsGb28181Device();
|
||||
device->device_id = id;
|
||||
device->device_status = status;
|
||||
if (status.find(",") != std::string::npos) {
|
||||
device->device_status = status.substr(0,status.find(","));
|
||||
device->device_name = status.substr(status.find(",")+1);
|
||||
} else {
|
||||
device->device_status = status;
|
||||
device->device_name = "NONAME";
|
||||
}
|
||||
device->invite_status = SrsGb28181SipSessionUnkonw;
|
||||
device->invite_time = 0;
|
||||
_device_list[id] = device;
|
||||
|
||||
}else {
|
||||
SrsGb28181Device *device = _device_list[id];
|
||||
device->device_status = status;
|
||||
if (status.find(",") != std::string::npos) {
|
||||
device->device_status = status.substr(0,status.find(","));
|
||||
device->device_name = status.substr(status.find(",")+1);
|
||||
} else {
|
||||
device->device_status = status;
|
||||
device->device_name = "NONAME";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SrsGb28181SipSession::clear_device_list()
|
||||
{
|
||||
//destory all device
|
||||
std::map<std::string, SrsGb28181Device*>::iterator it;
|
||||
for (it = _device_list.begin(); it != _device_list.end(); ++it) {
|
||||
srs_freep(it->second);
|
||||
}
|
||||
|
||||
_device_list.clear();
|
||||
}
|
||||
|
||||
SrsGb28181Device* SrsGb28181SipSession::get_device_info(std::string chid)
|
||||
{
|
||||
if (_device_list.find(chid) != _device_list.end()){
|
||||
|
@ -372,12 +398,33 @@ void SrsGb28181SipSession::dumps(SrsJsonObject* obj)
|
|||
SrsJsonObject* obj = SrsJsonAny::object();
|
||||
arr->append(obj);
|
||||
obj->set("device_id", SrsJsonAny::str(device->device_id.c_str()));
|
||||
obj->set("device_name", SrsJsonAny::str(device->device_name.c_str()));
|
||||
obj->set("device_status", SrsJsonAny::str(device->device_status.c_str()));
|
||||
obj->set("invite_status", SrsJsonAny::str(srs_get_sip_session_status_str(device->invite_status).c_str()));
|
||||
obj->set("invite_time", SrsJsonAny::integer(device->invite_time/SRS_UTIME_SECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
void SrsGb28181SipSession::dumpItemList(SrsJsonObject* obj)
|
||||
{
|
||||
obj->set("TopDeviceID", SrsJsonAny::str(_session_id.c_str()));
|
||||
obj->set("SumNum", SrsJsonAny::integer(item_list_sumnum));
|
||||
obj->set("RealSumNum", SrsJsonAny::integer(item_list.size()));
|
||||
|
||||
SrsJsonArray* arr = SrsJsonAny::array();
|
||||
obj->set("ItemList", arr);
|
||||
std::map<std::string, std::map<std::string, std::string> >::iterator it;
|
||||
for (it = item_list.begin(); it != item_list.end(); ++it) {
|
||||
std::map<std::string, std::string> device = it->second;
|
||||
SrsJsonObject* obj2 = SrsJsonAny::object();
|
||||
arr->append(obj2);
|
||||
std::map<std::string, std::string>::iterator it2;
|
||||
for (it2 = device.begin(); it2 != device.end(); ++it2) {
|
||||
obj2->set(it2->first, SrsJsonAny::str(it2->second.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//gb28181 sip Service
|
||||
SrsGb28181SipService::SrsGb28181SipService(SrsConfDirective* c)
|
||||
{
|
||||
|
@ -419,7 +466,9 @@ srs_error_t SrsGb28181SipService::on_udp_packet(const sockaddr* from, const int
|
|||
(char*)&address_string, sizeof(address_string),
|
||||
(char*)&port_string, sizeof(port_string),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV)) {
|
||||
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address");
|
||||
// return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address");
|
||||
srs_warn("gb28181: bad address");
|
||||
return srs_success;
|
||||
}
|
||||
std::string peer_ip = std::string(address_string);
|
||||
int peer_port = atoi(port_string);
|
||||
|
@ -427,7 +476,10 @@ srs_error_t SrsGb28181SipService::on_udp_packet(const sockaddr* from, const int
|
|||
std::string recv_msg(buf, nb_buf);
|
||||
srs_error_t err = on_udp_sip(peer_ip, peer_port, recv_msg, (sockaddr*)from, fromlen);
|
||||
if (err != srs_success) {
|
||||
return srs_error_wrap(err, "process udp");
|
||||
// return srs_error_wrap(err, "process udp");
|
||||
srs_warn("gb28181: process udp");
|
||||
srs_freep(err);
|
||||
return srs_success;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -465,11 +517,11 @@ srs_error_t SrsGb28181SipService::on_udp_sip(string peer_ip, int peer_port,
|
|||
return srs_error_new(ERROR_GB28181_SIP_PRASE_FAILED, "register string split");
|
||||
}
|
||||
|
||||
if (serial.at(0) != config->sip_serial){
|
||||
srs_warn("gb28181: client:%s request serial and server serial inconformity(%s:%s)",
|
||||
req->sip_auth_id.c_str(), serial.at(0).c_str(), config->sip_serial.c_str());
|
||||
return err;
|
||||
}
|
||||
//if (serial.at(0) != config->sip_serial){
|
||||
// srs_warn("gb28181: client:%s request serial and server serial inconformity(%s:%s)",
|
||||
// req->sip_auth_id.c_str(), serial.at(0).c_str(), config->sip_serial.c_str());
|
||||
// return err;
|
||||
//}
|
||||
|
||||
srs_trace("gb28181: request client id=%s peer(%s, %d)", req->sip_auth_id.c_str(), peer_ip.c_str(), peer_port);
|
||||
srs_trace("gb28181: %s method=%s, uri=%s, version=%s expires=%d",
|
||||
|
@ -519,6 +571,24 @@ srs_error_t SrsGb28181SipService::on_udp_sip(string peer_ip, int peer_port,
|
|||
if (req->device_list_map.size() > 0){
|
||||
sip_session->update_device_list(req->device_list_map);
|
||||
}
|
||||
if (!strcasecmp(req->content_type.c_str(),"application/manscdp+xml")
|
||||
&& req->xml_body_map.find("Response@CmdType") != req->xml_body_map.end()
|
||||
&& req->xml_body_map["Response@CmdType"] == "Catalog") {
|
||||
if (req->xml_body_map.find("Response@SumNum") != req->xml_body_map.end()) {
|
||||
sip_session->item_list_sumnum = atoi(req->xml_body_map["Response@SumNum"].c_str());
|
||||
}
|
||||
std::vector<std::map<std::string, std::string> >::iterator it;
|
||||
for (it = req->item_list.begin(); it != req->item_list.end(); ++it) {
|
||||
std::map<std::string, std::string> device = *it;
|
||||
std::map<std::string, std::map<std::string, std::string> >::iterator it2 = sip_session->item_list.find(device["DeviceID"]);
|
||||
if (it2 != sip_session->item_list.end()) {
|
||||
sip_session->item_list.erase(it2);
|
||||
sip_session->item_list[device["DeviceID"]] = device;
|
||||
} else {
|
||||
sip_session->item_list[device["DeviceID"]] = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else if (req->is_invite()) {
|
||||
|
@ -547,6 +617,14 @@ srs_error_t SrsGb28181SipService::on_udp_sip(string peer_ip, int peer_port,
|
|||
srs_trace("gb28181: INVITE response %s client status=%s", req->sip_auth_id.c_str(), req->status.c_str());
|
||||
|
||||
if (req->status == "200") {
|
||||
srs_trace("gb28181: device unique id is %s@%s", sip_session->session_id().c_str(), req->sip_auth_id.c_str());
|
||||
// if srs is external realm, ssrc is generated by source realm rather than srs
|
||||
// so update ssrc to the y line in source realm '200 OK' response
|
||||
// actually, we should do this all the time
|
||||
if (req->y_ssrc != 0) {
|
||||
_srs_gb28181->update_rtmpmuxer_to_newssrc_by_id(sip_session->session_id()+"@"+req->sip_auth_id, req->y_ssrc);
|
||||
req->y_ssrc = 0;
|
||||
}
|
||||
send_ack(req, from, fromlen);
|
||||
SrsGb28181Device *device = sip_session->get_device_info(req->sip_auth_id);
|
||||
if (device){
|
||||
|
@ -919,6 +997,31 @@ srs_error_t SrsGb28181SipService::query_sip_session(std::string sid, SrsJsonArr
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsGb28181SipService::query_device_list(std::string sid, SrsJsonArray* arr)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!sid.empty()){
|
||||
SrsGb28181SipSession* sess = fetch(sid);
|
||||
if (!sess){
|
||||
return srs_error_new(ERROR_GB28181_SESSION_IS_NOTEXIST, "sip session not exist");
|
||||
}
|
||||
SrsJsonObject* obj = SrsJsonAny::object();
|
||||
arr->append(obj);
|
||||
sess->dumpItemList(obj);
|
||||
}else {
|
||||
std::map<std::string, SrsGb28181SipSession*>::iterator it;
|
||||
for (it = sessions.begin(); it != sessions.end(); ++it) {
|
||||
SrsGb28181SipSession* sess = it->second;
|
||||
SrsJsonObject* obj = SrsJsonAny::object();
|
||||
arr->append(obj);
|
||||
sess->dumpItemList(obj);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsGb28181SipService::fetch_or_create_sip_session(SrsSipRequest *req, SrsGb28181SipSession** sip_session)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue