mirror of
https://github.com/gowvp/gb28181.git
synced 2025-09-27 03:45:57 +08:00
151 lines
2.9 KiB
Go
151 lines
2.9 KiB
Go
package sip
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"math"
|
|
"net"
|
|
"strings"
|
|
)
|
|
|
|
const abortIndex int8 = math.MaxInt8 >> 1
|
|
|
|
type HandlerFunc func(*Context)
|
|
|
|
type Context struct {
|
|
Request *Request
|
|
Tx *Transaction
|
|
handlers []HandlerFunc
|
|
index int8
|
|
|
|
cache map[string]any
|
|
|
|
DeviceID string
|
|
Host string
|
|
Port string
|
|
|
|
Source net.Addr
|
|
To *Address
|
|
From *Address
|
|
|
|
Log *slog.Logger
|
|
|
|
svr *Server
|
|
}
|
|
|
|
func newContext(req *Request, tx *Transaction) *Context {
|
|
c := Context{
|
|
Request: req,
|
|
Tx: tx,
|
|
cache: make(map[string]any),
|
|
Log: slog.Default(),
|
|
index: -1,
|
|
}
|
|
if err := c.parserRequest(); err != nil {
|
|
slog.Error("parserRequest", "err", err)
|
|
}
|
|
return &c
|
|
}
|
|
|
|
func (c *Context) parserRequest() error {
|
|
req := c.Request
|
|
header, ok := req.From()
|
|
if !ok {
|
|
return fmt.Errorf("req from is nil")
|
|
}
|
|
|
|
if header.Address == nil {
|
|
return fmt.Errorf("header address is nil")
|
|
}
|
|
user := header.Address.User()
|
|
if user == nil {
|
|
return fmt.Errorf("address user is nil")
|
|
}
|
|
c.DeviceID = user.String()
|
|
c.Host = header.Address.Host()
|
|
via, ok := req.ViaHop()
|
|
if !ok {
|
|
return fmt.Errorf("via is nil")
|
|
}
|
|
c.Host = via.Host
|
|
c.Port = via.Port.String()
|
|
|
|
c.Source = req.Source()
|
|
c.To = NewAddressFromFromHeader(header)
|
|
if c.To == nil {
|
|
slog.Error(">>>>>>>> to is nil", "header", header)
|
|
}
|
|
|
|
c.Log = slog.Default().With("deviceID", c.DeviceID, "host", c.Host)
|
|
return nil
|
|
}
|
|
|
|
func (c *Context) Next() {
|
|
c.index++
|
|
for c.index < int8(len(c.handlers)) {
|
|
if fn := c.handlers[c.index]; fn != nil {
|
|
fn(c)
|
|
}
|
|
c.index++
|
|
}
|
|
}
|
|
|
|
func (c *Context) GetHeader(key string) string {
|
|
headers := c.Request.GetHeaders(key)
|
|
if len(headers) > 0 {
|
|
header := headers[0]
|
|
splits := strings.Split(header.String(), ":")
|
|
if len(splits) == 2 {
|
|
return strings.TrimSpace(splits[1])
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (c *Context) Abort() {
|
|
c.index = abortIndex
|
|
}
|
|
|
|
func (c *Context) AbortString(status int, msg string) {
|
|
c.Abort()
|
|
c.String(status, msg)
|
|
}
|
|
|
|
func (c *Context) String(status int, msg string) {
|
|
_ = c.Tx.Respond(NewResponseFromRequest("", c.Request, status, msg, nil))
|
|
}
|
|
|
|
func (c *Context) Set(k string, v any) {
|
|
c.cache[k] = v
|
|
}
|
|
|
|
func (c *Context) Get(k string) (any, bool) {
|
|
v, ok := c.cache[k]
|
|
return v, ok
|
|
}
|
|
|
|
func (c *Context) GetMustString(k string) string {
|
|
if v, ok := c.cache[k]; ok {
|
|
return v.(string)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (c *Context) GetMustInt(k string) int {
|
|
if v, ok := c.cache[k]; ok {
|
|
return v.(int)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (c *Context) SendRequest(method string, body []byte) (*Transaction, error) {
|
|
hb := NewHeaderBuilder().SetTo(c.To).SetFrom(c.From).AddVia(&ViaHop{
|
|
Params: NewParams().Add("branch", String{Str: GenerateBranch()}),
|
|
}).SetContentType(&ContentTypeXML).SetMethod(method)
|
|
|
|
req := NewRequest("", method, c.To.URI, DefaultSipVersion, hb.Build(), body)
|
|
req.SetDestination(c.Source)
|
|
req.SetConnection(c.Request.conn)
|
|
return c.svr.Request(req)
|
|
}
|