catalog 实现

sipgo udp MTU 1500 限制, 数据包大于 1500 会报错
This commit is contained in:
shikong 2025-01-24 17:33:04 +08:00
parent c18573d730
commit eb1219c2fe
Signed by: Shikong
GPG Key ID: BD85FF18B373C341
5 changed files with 218 additions and 11 deletions

View File

@ -1,26 +1,42 @@
package main
import (
"context"
"fmt"
"encoding/xml"
"git.skcks.cn/Shikong/go-gb28181/pkg/config"
"git.skcks.cn/Shikong/go-gb28181/pkg/logger"
"git.skcks.cn/Shikong/go-gb28181/pkg/manscdp"
"git.skcks.cn/Shikong/go-gb28181/pkg/utils"
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
"github.com/rs/zerolog"
"time"
"context"
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
output := zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) {
w.Out = os.Stdout
w.TimeFormat = time.RFC3339
})
logger := zerolog.New(output).With().Timestamp().Logger()
clientConfig, err := config.ReadClientConfig()
if err != nil {
logger.Log().Fatal(err)
logger.Fatal().Any("%s", err)
return
}
fmt.Printf("%+v\n", clientConfig)
sip.SIPDebug = clientConfig.Debug
if clientConfig.Debug {
sip.SIPDebug = clientConfig.Debug
logger = logger.Level(zerolog.DebugLevel)
} else {
logger = logger.Level(zerolog.InfoLevel)
}
ctx := context.Background()
@ -29,19 +45,92 @@ func main() {
sipgo.WithUserAgent(clientConfig.DeviceId),
sipgo.WithUserAgentHostname(addr))
srv, _ := sipgo.NewServer(ua)
srv, _ := sipgo.NewServer(ua, sipgo.WithServerLogger(logger))
srv.OnMessage(func(req *sip.Request, tx sip.ServerTransaction) {
query := new(manscdp.CatalogReq)
_ = utils.XMLUnmarshal(req.Body(), query)
logger.Info().Msgf("收到查询指令: %s\n%+v\n", query.CmdType, query)
//response := sip.NewResponse(sip.StatusOK, "OK")
//err = tx.Respond(response)
//if err != nil {
// logger.Error().Err(err)
//}
tx.Done()
go func() {
client, _ := sipgo.NewClient(ua,
sipgo.WithClientHostname(clientConfig.ListenIp),
sipgo.WithClientPort(clientConfig.ListenPort))
resp := new(manscdp.CatalogResp)
resp.XMLName = xml.Name{Local: "Response"}
resp.DeviceID = clientConfig.DeviceId
resp.CmdType = "Catalog"
resp.SumNum = "1"
resp.DeviceList = new(manscdp.CateLogDeviceList)
resp.DeviceList.XMLName = xml.Name{Local: "DeviceList"}
resp.DeviceList.Num = "1"
resp.DeviceList.Item = make([]manscdp.CateLogDevice, 1)
resp.DeviceList.Item[0].DeviceID = "44050100002000000002"
resp.DeviceList.Item[0].Name = "设备名称"
resp.DeviceList.Item[0].Manufacturer = "设备厂商"
resp.DeviceList.Item[0].ErrCode = "0"
resp.DeviceList.Item[0].Port = fmt.Sprintf("%d", clientConfig.ListenPort)
resp.SN = query.SN
marshal, _ := utils.XMLMarshal(resp, "gbk")
logger.Info().Msgf("回复查询指令: %s\n%+v\n", query.CmdType, resp)
target := sip.Uri{
User: clientConfig.ServerId,
Host: clientConfig.ServerIp,
Port: clientConfig.ServerPort,
Headers: sip.NewParams(),
}
time.Sleep(time.Second * 1)
//uri := sip.Uri{User: "44050100002000000002", Host: "10.10.10.20", Port: 5099}
nReq := sip.NewRequest(sip.MESSAGE, target)
nReq.SetTransport("UDP")
to := sip.NewHeader("To", req.GetHeader("From").Value())
from := sip.NewHeader("From", req.GetHeader("To").Value())
nReq.AppendHeader(to)
nReq.AppendHeader(from)
//nReq.AppendHeader(req.GetHeader("Call-ID"))
nReq.AppendHeader(sip.NewHeader("Content-Type", "Application/MANSCDP+xml"))
nReq.SetBody(marshal)
err := sipgo.ClientRequestBuild(client, nReq)
if err != nil {
logger.Error().Err(err)
}
logger.Info().Msgf("向服务器发送查询指令: %s\n%+v\n", query.CmdType, nReq)
err = client.WriteRequest(nReq)
if err != nil {
logger.Error().Err(err)
return
}
_ = client.Close()
logger.Info().Msgf("向服务器发送查询指令完成")
}()
})
quit := make(chan os.Signal, 1)
go func() {
defer func() {
if err := recover(); err != nil {
logger.Log().Error(err)
logger.Fatal().Any("%s", err)
quit <- syscall.SIGKILL
}
}()
if err := srv.ListenAndServe(ctx, "udp", addr); err != nil {
logger.Log().Error(err)
logger.Error().Err(err)
quit <- syscall.SIGTERM
}
}()

1
go.mod
View File

@ -4,7 +4,6 @@ go 1.23.5
require (
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/duke-git/lancet/v2 v2.3.4
github.com/emiago/sipgo v0.28.0
github.com/icholy/digest v1.1.0
github.com/pelletier/go-toml/v2 v2.2.2

2
go.sum
View File

@ -7,8 +7,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/duke-git/lancet/v2 v2.3.4 h1:8XGI7P9w+/GqmEBEXYaH/XuNiM0f4/90Ioti0IvYJls=
github.com/duke-git/lancet/v2 v2.3.4/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc=
github.com/emiago/sipgo v0.28.0 h1:wW9W+p89ldLbKOhXhj9BHo6U39vuWdUc0WVZ+E3rk6Y=
github.com/emiago/sipgo v0.28.0/go.mod h1:ZQ/tl5t+3assyOjiKw/AInPkcawBJ2Or+d5buztOZsc=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=

52
pkg/manscdp/catalog.go Normal file
View File

@ -0,0 +1,52 @@
package manscdp
import "encoding/xml"
type CatalogReq struct {
XMLName xml.Name `xml:"Query"`
CmdType string `xml:"CmdType"`
SN string `xml:"SN"`
DeviceID string `xml:"DeviceID"`
}
type CatalogResp struct {
XMLName xml.Name `xml:"Response"`
CmdType string `xml:"CmdType"`
SumNum string `xml:"SumNum"`
DeviceList *CateLogDeviceList `xml:"DeviceList"`
SN string `xml:"SN"`
DeviceID string `xml:"DeviceID"`
}
type CateLogDeviceList struct {
XMLName xml.Name `xml:"DeviceList"`
Num string `xml:"Num,attr"`
Item []CateLogDevice `xml:"Item"`
}
type CateLogDevice struct {
XMLName xml.Name `xml:"Item"`
Name string `xml:"Name"`
Manufacturer string `xml:"Manufacturer"`
Model string `xml:"Model"`
Owner string `xml:"Owner"`
Block string `xml:"Block"`
Address string `xml:"Address"`
Parental string `xml:"Parental"`
SafetyWay string `xml:"SafetyWay"`
RegisterWay string `xml:"RegisterWay"`
CertNum string `xml:"CertNum"`
Certifiable string `xml:"Certifiable"`
ErrCode string `xml:"ErrCode"`
EndTime string `xml:"EndTime"`
Secrecy string `xml:"Secrecy"`
Port string `xml:"Port"`
Password string `xml:"Password"`
Status string `xml:"Status"`
Longitude string `xml:"Longitude"`
Latitude string `xml:"Latitude"`
DeviceID string `xml:"DeviceID"`
CivilCode string `xml:"CivilCode"`
ParentID string `xml:"ParentID"`
IPAddress string `xml:"IPAddress"`
}

View File

@ -2,7 +2,10 @@ package test
import (
"context"
"encoding/xml"
"fmt"
"git.skcks.cn/Shikong/go-gb28181/pkg/manscdp"
"git.skcks.cn/Shikong/go-gb28181/pkg/utils"
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
"github.com/icholy/digest"
@ -130,6 +133,72 @@ func TestClient(t *testing.T) {
<-quit
}
func TestCatalog(t *testing.T) {
ua, _ := sipgo.NewUA(
sipgo.WithUserAgent("44050100002000000002"),
sipgo.WithUserAgentHostname("10.10.10.20:5099"))
client, _ := sipgo.NewClient(ua,
sipgo.WithClientHostname("10.10.10.20"),
sipgo.WithClientPort(5099))
resp := new(manscdp.CatalogResp)
resp.XMLName = xml.Name{Local: "Response"}
resp.DeviceID = "44050100002000000002"
resp.CmdType = "Catalog"
resp.SumNum = "1"
resp.DeviceList = new(manscdp.CateLogDeviceList)
resp.DeviceList.XMLName = xml.Name{Local: "DeviceList"}
resp.DeviceList.Num = "1"
resp.DeviceList.Item = make([]manscdp.CateLogDevice, 1)
resp.DeviceList.Item[0].DeviceID = "44050100002000000002"
resp.DeviceList.Item[0].Name = "设备名称"
resp.DeviceList.Item[0].Manufacturer = "设备厂商"
resp.DeviceList.Item[0].ErrCode = "0"
resp.DeviceList.Item[0].EndTime = "2022-12-31'T'23:59:59"
resp.DeviceList.Item[0].Port = fmt.Sprintf("%d", 5099)
resp.SN = "90000"
marshal, _ := utils.XMLMarshal(resp, "gb2312")
t.Logf("回复查询指令: %s\n%+v\n", "Catalog", resp)
target := sip.Uri{
User: "44050100002000000003",
Host: "10.10.10.20",
Port: 5060,
Headers: sip.NewParams(),
}
time.Sleep(time.Second * 1)
//uri := sip.Uri{User: "44050100002000000002", Host: "10.10.10.20", Port: 5099}
nReq := sip.NewRequest(sip.MESSAGE, target)
nReq.SetTransport("UDP")
//to := sip.NewHeader("To", req.GetHeader("From").Value())
//from := sip.NewHeader("From", req.GetHeader("To").Value())
//nReq.AppendHeader(to)
//nReq.AppendHeader(from)
//nReq.AppendHeader(req.GetHeader("Call-ID"))
nReq.AppendHeader(sip.NewHeader("Content-Type", "Application/MANSCDP+xml"))
nReq.SetBody(marshal)
err := sipgo.ClientRequestBuild(client, nReq)
//if err != nil {
// logger.Error().Err(err)
//}
t.Logf("向服务器发送查询指令: %s\n%+v\n", "Catalog", nReq)
client.TransactionLayer()
_, err = client.TransactionRequest(context.Background(), nReq)
if err != nil {
t.Fatal(err)
return
}
_ = client.Close()
t.Log("向服务器发送查询指令完成")
}
func getResponse(tx sip.ClientTransaction) (*sip.Response, error) {
select {
case <-tx.Done():