From eb1219c2fe07bc91d1a285a278a97051793ef984 Mon Sep 17 00:00:00 2001 From: shikong <919411476@qq.com> Date: Fri, 24 Jan 2025 17:33:04 +0800 Subject: [PATCH] =?UTF-8?q?catalog=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sipgo udp MTU 1500 限制, 数据包大于 1500 会报错 --- cmd/client/main.go | 105 +++++++++++++++++++++++++++++++++++++---- go.mod | 1 - go.sum | 2 - pkg/manscdp/catalog.go | 52 ++++++++++++++++++++ test/client_test.go | 69 +++++++++++++++++++++++++++ 5 files changed, 218 insertions(+), 11 deletions(-) create mode 100644 pkg/manscdp/catalog.go diff --git a/cmd/client/main.go b/cmd/client/main.go index 5710e58..7c6293f 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -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 } }() diff --git a/go.mod b/go.mod index 28da73b..7c73c5c 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 802bee9..7e2a796 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/pkg/manscdp/catalog.go b/pkg/manscdp/catalog.go new file mode 100644 index 0000000..856e6d5 --- /dev/null +++ b/pkg/manscdp/catalog.go @@ -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"` +} diff --git a/test/client_test.go b/test/client_test.go index 34b5e80..48d701e 100644 --- a/test/client_test.go +++ b/test/client_test.go @@ -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():