实现启动时注册 register

This commit is contained in:
shikong 2025-01-25 17:47:00 +08:00
parent c76f5dcca7
commit 838d64ebff
Signed by: Shikong
GPG Key ID: BD85FF18B373C341
3 changed files with 110 additions and 7 deletions

View File

@ -60,16 +60,11 @@ func main() {
// 服务端, 接受 SIP 指令 // 服务端, 接受 SIP 指令
srv, _ := sipgo.NewServer(ua, sipgo.WithServerLogger(logger)) srv, _ := sipgo.NewServer(ua, sipgo.WithServerLogger(logger))
message.SetupMessageHandler(srv, client, clientConfig)
keepalive.SetupKeepalive(client, clientConfig)
device.StartKeepAlive(client)
defer device.StopKeepAlive()
quit := make(chan os.Signal, 1) quit := make(chan os.Signal, 1)
go func() { go func() {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
logger.Fatal().Any("%s", err) logger.Error().Msgf("%s", err)
quit <- syscall.SIGKILL quit <- syscall.SIGKILL
} }
}() }()
@ -77,11 +72,19 @@ func main() {
// 暂时 默认 udp // 暂时 默认 udp
// 启动 SIP 服务 // 启动 SIP 服务
if err := srv.ListenAndServe(ctx, "udp", addr); err != nil { if err := srv.ListenAndServe(ctx, "udp", addr); err != nil {
logger.Error().Err(err) logger.Error().Msgf("%s", err)
quit <- syscall.SIGTERM quit <- syscall.SIGTERM
} }
}() }()
time.Sleep(1 * time.Second)
device.Register(client, clientConfig)
message.SetupMessageHandler(srv, client, clientConfig)
keepalive.SetupKeepalive(client, clientConfig)
device.StartKeepAlive(client)
defer device.StopKeepAlive()
signal.Notify(quit, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM) signal.Notify(quit, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)
<-quit <-quit
} }

View File

@ -18,6 +18,7 @@ func AddKeepaliveSender(deviceId string, sender SendKeepAlive) {
} }
// StartKeepAlive 启动 keepalive 定时器 // StartKeepAlive 启动 keepalive 定时器
//
// 每 30 秒发送一次 keepalive 消息到服务器 // 每 30 秒发送一次 keepalive 消息到服务器
func StartKeepAlive(client *sipgo.Client) { func StartKeepAlive(client *sipgo.Client) {
keepaliveTimer = time.NewTicker(time.Second * 30) keepaliveTimer = time.NewTicker(time.Second * 30)

View File

@ -0,0 +1,99 @@
package device
import (
"context"
"fmt"
"git.skcks.cn/Shikong/go-gb28181/pkg/config"
"git.skcks.cn/Shikong/go-gb28181/pkg/log"
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
"github.com/icholy/digest"
"time"
)
func Register(client *sipgo.Client, clientConfig *config.ClientConfig) {
target := sip.Uri{
User: clientConfig.ServerId,
Host: clientConfig.ServerIp,
Port: clientConfig.ServerPort,
Headers: sip.NewParams(),
}
uri := sip.Uri{User: clientConfig.DeviceId, Host: clientConfig.ListenIp, Port: clientConfig.ServerPort}
req := sip.NewRequest(sip.REGISTER, target)
req.AppendHeader(sip.NewHeader("X-GB-Ver", "2.0"))
req.AppendHeader(sip.NewHeader("Contact", uri.String()))
req.AppendHeader(sip.NewHeader("Expires", "3600"))
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
tx, err := client.TransactionRequest(ctx, req)
defer tx.Terminate()
if err != nil {
log.Log().Error().Msgf("%v", err)
return
}
resp, err := getResponse(tx)
if err != nil {
log.Log().Error().Msgf("%v", err)
return
}
headers := resp.Headers()
for _, h := range headers {
log.Log().Info().Msgf("%v => %v", h.Name(), h.Value())
}
log.Log().Info().Msgf(resp.String())
// 如果状态码是401则需要验证
if resp.StatusCode == 401 {
wwwAuth := resp.GetHeader("WWW-Authenticate")
chal, err := digest.ParseChallenge(wwwAuth.Value())
if err != nil {
log.Log().Error().Msgf("Fail to parse challenge %v", err)
return
}
// Reply with digest
cred, _ := digest.Digest(chal, digest.Options{
Method: req.Method.String(),
Username: clientConfig.ServerId,
URI: target.String(),
Password: clientConfig.Password,
})
newReq := req.Clone()
newReq.RemoveHeader("Via") // Must be regenerated by tranport layer
newReq.AppendHeader(sip.NewHeader("Authorization", cred.String()))
ctx := context.Background()
tx, err := client.TransactionRequest(ctx, newReq, sipgo.ClientRequestAddVia)
if err != nil {
log.Log().Error().Msgf("Fail to create transaction")
return
}
resp, err = getResponse(tx)
defer tx.Terminate()
if err != nil {
log.Log().Error().Msgf("Fail to get response")
return
}
if resp.StatusCode != 403 {
log.Log().Info().Msgf("设备:%s 注册成功", clientConfig.DeviceId)
}
log.Log().Info().Msgf(resp.String())
}
}
func getResponse(tx sip.ClientTransaction) (*sip.Response, error) {
select {
case <-tx.Done():
return nil, fmt.Errorf("transaction died")
case res := <-tx.Responses():
return res, nil
}
}