mirror of
https://github.com/lkmio/gb-cms.git
synced 2025-12-24 11:51:52 +08:00
feat: 支持ip转地址
This commit is contained in:
@@ -39,10 +39,12 @@ func (api *ApiServer) OnDeviceList(q *QueryDeviceChannel, _ http.ResponseWriter,
|
||||
}
|
||||
|
||||
response := struct {
|
||||
DeviceCount int
|
||||
DeviceList_ []LiveGBSDevice `json:"DeviceList"`
|
||||
DeviceCount int
|
||||
DeviceList_ []LiveGBSDevice `json:"DeviceList"`
|
||||
DeviceRegion bool
|
||||
}{
|
||||
DeviceCount: total,
|
||||
DeviceCount: total,
|
||||
DeviceRegion: common.Config.IP2RegionEnable,
|
||||
}
|
||||
|
||||
// livgbs设备离线后的最后心跳时间, 涉及到是否显示非法设备的批量删除按钮
|
||||
@@ -89,8 +91,8 @@ func (api *ApiServer) OnDeviceList(q *QueryDeviceChannel, _ http.ResponseWriter,
|
||||
KeepOriginalTree: false,
|
||||
LastKeepaliveAt: lastKeealiveTime,
|
||||
LastRegisterAt: device.RegisterTime.Format("2006-01-02 15:04:05"),
|
||||
Latitude: 0,
|
||||
Longitude: 0,
|
||||
Latitude: device.Latitude,
|
||||
Longitude: device.Longitude,
|
||||
//Manufacturer: device.Manufacturer,
|
||||
Manufacturer: device.UserAgent,
|
||||
MediaTransport: device.GetSetup().Transport(),
|
||||
@@ -105,7 +107,7 @@ func (api *ApiServer) OnDeviceList(q *QueryDeviceChannel, _ http.ResponseWriter,
|
||||
RecvStreamIP: "",
|
||||
RemoteIP: device.RemoteIP,
|
||||
RemotePort: device.RemotePort,
|
||||
RemoteRegion: "",
|
||||
RemoteRegion: device.RemoteRegion,
|
||||
SMSGroupID: "",
|
||||
SMSID: "",
|
||||
StreamMode: "",
|
||||
|
||||
@@ -221,6 +221,10 @@ func (api *ApiServer) OnSetBaseConfig(baseConfig *BaseConfig, _ http.ResponseWri
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ip库只在启动时加载
|
||||
newConfig.IP2RegionEnable = common.Config.IP2RegionEnable
|
||||
newConfig.IP2RegionDBPath = common.Config.IP2RegionDBPath
|
||||
|
||||
// 重启sip服务
|
||||
if sipChanged {
|
||||
log.Sugar.Infof("重启sip服务器 port: %d", baseConfig.Port)
|
||||
|
||||
@@ -45,6 +45,9 @@ type Config_ struct {
|
||||
Position string `json:"position"`
|
||||
OnInvite string `json:"on_invite"`
|
||||
}
|
||||
|
||||
IP2RegionDBPath string
|
||||
IP2RegionEnable bool
|
||||
}
|
||||
|
||||
type LogConfig struct {
|
||||
@@ -84,6 +87,8 @@ func ParseConfig(path string) (*Config_, error) {
|
||||
SubPTZGlobalInterval: load.Section("sip").Key("sub_ptz_global_interval").MustInt(),
|
||||
DeviceDefaultMediaTransport: load.Section("sip").Key("device_default_media_transport").String(),
|
||||
GlobalDropChannelType: load.Section("sip").Key("global_drop_channel_type").String(),
|
||||
IP2RegionDBPath: load.Section("ip2region").Key("db_path").String(),
|
||||
IP2RegionEnable: load.Section("ip2region").Key("enable").MustBool(),
|
||||
}
|
||||
|
||||
config_.Hooks.Online = load.Section("hooks").Key("online").String()
|
||||
|
||||
65
common/ip2region.go
Normal file
65
common/ip2region.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
searcher *xdb.Searcher
|
||||
)
|
||||
|
||||
func LoadIP2RegionDB(path string) error {
|
||||
// 1、从 dbPath 加载整个 xdb 到内存
|
||||
cBuff, err := xdb.LoadContentFromFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2、用全局的 cBuff 创建完全基于内存的查询对象。
|
||||
searcher, err = xdb.NewWithBuffer(xdb.IPv4, cBuff)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IP2Region(ip string) (string, error) {
|
||||
// 3、查询
|
||||
region, err := searcher.SearchByStr(ip)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 合并成一个地址
|
||||
var addressList []string
|
||||
for _, address := range strings.Split(region, "|") {
|
||||
if address == "" || address == "中国" || address == "0" {
|
||||
continue
|
||||
}
|
||||
|
||||
var same bool
|
||||
for _, s := range addressList {
|
||||
if s == address {
|
||||
same = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if same {
|
||||
continue
|
||||
}
|
||||
|
||||
addressList = append(addressList, address)
|
||||
}
|
||||
|
||||
if length := len(addressList); length == 0 {
|
||||
return "", nil
|
||||
} else if length > 1 {
|
||||
// 最后一个地址空格分开
|
||||
addressList[length-2] += " "
|
||||
}
|
||||
|
||||
return strings.Join(addressList, ""), nil
|
||||
}
|
||||
11
config.ini
11
config.ini
@@ -18,7 +18,7 @@ alarm_reserve_days = 3
|
||||
# invite超时时间, 单位秒
|
||||
invite_timeout = 10
|
||||
# udp/passive/active, 优先级小于设备的setup字段
|
||||
device_default_media_transport = active
|
||||
device_default_media_transport = passive
|
||||
# 媒体服务器地址
|
||||
media_server = http://0.0.0.0:8080
|
||||
# 前端拉流优先使用的流格式, FLV/WS_FLV/WEBRTC/RTMP/HLS
|
||||
@@ -46,8 +46,7 @@ on_invite = http://localhost:8081/api/v1/jt1078/on_invite
|
||||
# 被查询录像,用于通知1078信令服务器
|
||||
on_query_record =
|
||||
|
||||
[subscribe]
|
||||
alarm = 3600
|
||||
catalog = 3600
|
||||
ptz = 3600
|
||||
position = 3600
|
||||
[ip2region]
|
||||
# ip2region数据库路径, 更新地址: https://github.com/lionsoul2014/ip2region/tree/master/data
|
||||
db_path = ip2region_v4.xdb
|
||||
enable = 1
|
||||
|
||||
@@ -2,6 +2,7 @@ package dao
|
||||
|
||||
import (
|
||||
"gb-cms/common"
|
||||
"gb-cms/log"
|
||||
"gorm.io/gorm"
|
||||
"net"
|
||||
"strconv"
|
||||
@@ -19,6 +20,7 @@ type DeviceModel struct {
|
||||
Name string `json:"name" gorm:"index"`
|
||||
RemoteIP string `json:"remote_ip"`
|
||||
RemotePort int `json:"remote_port"`
|
||||
RemoteRegion string `json:"remote_region"`
|
||||
Transport string `json:"transport"` // 信令传输模式 UDP/TCP
|
||||
Status common.OnlineStatus `json:"status"` // 在线状态 ON-在线/OFF-离线
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
@@ -86,17 +88,26 @@ func (d *daoDevice) LoadDevices() (map[string]*DeviceModel, error) {
|
||||
}
|
||||
|
||||
func (d *daoDevice) SaveDevice(device *DeviceModel) error {
|
||||
return DBTransaction(func(tx *gorm.DB) error {
|
||||
old := DeviceModel{}
|
||||
if db.Select("id").Where("device_id =?", device.DeviceID).Take(&old).Error == nil {
|
||||
device.ID = old.ID
|
||||
old := DeviceModel{}
|
||||
if db.Select("id", "remote_ip", "remote_region").Where("device_id =?", device.DeviceID).Take(&old).Error == nil {
|
||||
device.ID = old.ID
|
||||
}
|
||||
|
||||
if common.Config.IP2RegionEnable && (old.RemoteRegion == "" || (old.RemoteIP != "" && old.RemoteIP != device.RemoteIP)) {
|
||||
region, err := common.IP2Region(device.RemoteIP)
|
||||
if err != nil {
|
||||
log.Sugar.Errorf("IP2Region failed. err: %s", err.Error())
|
||||
}
|
||||
|
||||
device.RemoteRegion = region
|
||||
}
|
||||
|
||||
return DBTransaction(func(tx *gorm.DB) error {
|
||||
if device.ID == 0 {
|
||||
//return tx.Create(&old).Error
|
||||
return tx.Save(device).Error
|
||||
} else {
|
||||
return tx.Model(device).Select("Transport", "RemoteIP", "RemotePort", "Status", "RegisterTime", "LastHeartbeat").Updates(*device).Error
|
||||
return tx.Model(device).Select("transport", "remote_ip", "remote_port", "status", "register_time", "last_heartbeat", "remote_region").Updates(*device).Error
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -127,17 +138,29 @@ func (d *daoDevice) UpdateDeviceStatus(deviceId string, status common.OnlineStat
|
||||
}
|
||||
|
||||
func (d *daoDevice) RefreshHeartbeat(deviceId string, now time.Time, addr string) error {
|
||||
if tx := db.Select("id").Take(&DeviceModel{}, "device_id =?", deviceId); tx.Error != nil {
|
||||
old := DeviceModel{}
|
||||
if tx := db.Select("id", "remote_ip", "remote_region").Take(&old, "device_id =?", deviceId); tx.Error != nil {
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
host, p, _ := net.SplitHostPort(addr)
|
||||
var region = old.RemoteRegion
|
||||
if common.Config.IP2RegionEnable && (old.RemoteRegion == "" || (old.RemoteIP != "" && old.RemoteIP != host)) {
|
||||
var err error
|
||||
region, err = common.IP2Region(host)
|
||||
if err != nil {
|
||||
log.Sugar.Errorf("IP2Region failed. err: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return DBTransaction(func(tx *gorm.DB) error {
|
||||
host, p, _ := net.SplitHostPort(addr)
|
||||
port, _ := strconv.Atoi(p)
|
||||
return tx.Model(&DeviceModel{}).Select("LastHeartbeat", "Status", "RemoteIP", "RemotePort").Where("device_id =?", deviceId).Updates(&DeviceModel{
|
||||
return tx.Model(&DeviceModel{}).Select("last_heartbeat", "status", "remote_ip", "remote_port", "remote_region").Where("device_id =?", deviceId).Updates(&DeviceModel{
|
||||
LastHeartbeat: now,
|
||||
Status: common.ON,
|
||||
RemoteIP: host,
|
||||
RemotePort: port,
|
||||
RemoteRegion: region,
|
||||
}).Error
|
||||
})
|
||||
}
|
||||
|
||||
3
go.mod
3
go.mod
@@ -45,7 +45,6 @@ require (
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
golang.org/x/term v0.21.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
@@ -58,9 +57,11 @@ require (
|
||||
github.com/go-co-op/gocron/v2 v2.16.6
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20251031035847-91e542de380a
|
||||
github.com/lkmio/avformat v0.0.1
|
||||
github.com/pretty66/websocketproxy v0.0.0-20220507015215-930b3a686308
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gorm.io/gorm v1.26.1
|
||||
)
|
||||
|
||||
|
||||
BIN
ip2region_v4.xdb
Normal file
BIN
ip2region_v4.xdb
Normal file
Binary file not shown.
@@ -254,4 +254,13 @@ func Start() {
|
||||
)
|
||||
|
||||
s.Start()
|
||||
|
||||
// 加载ip2region数据库
|
||||
if common.Config.IP2RegionEnable {
|
||||
err := common.LoadIP2RegionDB(common.Config.IP2RegionDBPath)
|
||||
if err != nil {
|
||||
common.Config.IP2RegionEnable = false
|
||||
log.Sugar.Errorf("加载ip2region数据库失败. err: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user