Files
lkm/api_gb.go
2024-11-09 10:19:16 +08:00

185 lines
4.2 KiB
Go

package main
import (
"fmt"
"github.com/lkmio/avformat/utils"
"github.com/lkmio/lkm/gb28181"
"github.com/lkmio/lkm/log"
"github.com/lkmio/lkm/stream"
"net"
"net/http"
"strings"
)
type GBForwardParams struct {
Source string `json:"source"` //GetSourceID
Addr string `json:"addr"`
SSRC uint32 `json:"ssrc"`
Setup string `json:"setup"`
}
type GBSourceParams struct {
Source string `json:"source"` //GetSourceID
Setup string `json:"setup"` //active/passive
SSRC uint32 `json:"ssrc,omitempty"`
}
type GBConnect struct {
Source string `json:"source"` //GetSourceID
RemoteAddr string `json:"remote_addr"`
}
func (api *ApiServer) OnGBSourceCreate(v *GBSourceParams, w http.ResponseWriter, r *http.Request) {
log.Sugar.Infof("创建国标源: %v", v)
// 返回收流地址
response := &struct {
IP string `json:"ip"`
Port int `json:"port,omitempty"`
Urls []string `json:"urls"`
}{}
var err error
// 响应错误消息
defer func() {
if err != nil {
log.Sugar.Errorf("创建国标源失败 err: %s", err.Error())
httpResponseError(w, err.Error())
}
}()
source := stream.SourceManager.Find(v.Source)
if source != nil {
err = fmt.Errorf("%s 源已经存在", v.Source)
return
}
tcp := true
var active bool
if v.Setup == "passive" {
} else if v.Setup == "active" {
active = true
} else {
tcp = false
//udp收流
}
if tcp && active {
if !stream.AppConfig.GB28181.IsMultiPort() {
err = fmt.Errorf("单端口模式下不能主动拉流")
} else if !tcp {
err = fmt.Errorf("UDP不能主动拉流")
} else if !stream.AppConfig.GB28181.IsEnableTCP() {
err = fmt.Errorf("未开启TCP收流服务,UDP不能主动拉流")
}
if err != nil {
return
}
}
_, port, err := gb28181.NewGBSource(v.Source, v.SSRC, tcp, active)
if err != nil {
return
}
response.IP = stream.AppConfig.PublicIP
response.Port = port
response.Urls = stream.GetStreamPlayUrls(v.Source)
httpResponseOK(w, response)
}
func (api *ApiServer) OnGBSourceConnect(v *GBConnect, w http.ResponseWriter, r *http.Request) {
log.Sugar.Infof("设置国标主动拉流连接地址: %v", v)
var err error
// 响应错误消息
defer func() {
if err != nil {
log.Sugar.Errorf("设置国标主动拉流失败 err: %s", err.Error())
httpResponseError(w, err.Error())
}
}()
source := stream.SourceManager.Find(v.Source)
if source == nil {
err = fmt.Errorf("%s 源不存在", v.Source)
return
}
activeSource, ok := source.(*gb28181.ActiveSource)
if !ok {
err = fmt.Errorf("%s 源不是Active拉流类型", v.Source)
return
}
addr, err := net.ResolveTCPAddr("tcp", v.RemoteAddr)
if err != nil {
return
}
if err = activeSource.Connect(addr); err == nil {
httpResponseOK(w, nil)
}
}
func (api *ApiServer) OnGBSourceForward(v *GBForwardParams, w http.ResponseWriter, r *http.Request) {
log.Sugar.Infof("设置国标级联转发: %v", v)
var err error
// 响应错误消息
defer func() {
if err != nil {
log.Sugar.Errorf("设置级联转发失败 err: %s", err.Error())
httpResponseError(w, err.Error())
}
}()
source := stream.SourceManager.Find(v.Source)
if source == nil {
err = fmt.Errorf("%s 源不存在", v.Source)
} else if source.GetType() != stream.SourceType28181 {
log.Sugar.Infof("%s 源不是国标推流类型", v.Source)
return
}
var setup gb28181.SetupType
switch strings.ToLower(v.Setup) {
case "active":
setup = gb28181.SetupActive
break
case "passive":
setup = gb28181.SetupPassive
break
default:
setup = gb28181.SetupUDP
break
}
addr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
sinkId := stream.NetAddr2SinkId(addr)
// 添加随机数
if ipv4, ok := sinkId.(uint64); ok {
random := uint64(utils.RandomIntInRange(0x1000, 0xFFFF0000))
sinkId = (ipv4 & 0xFFFFFFFF00000000) | (random << 16) | (ipv4 & 0xFFFF)
}
sink, port, err := gb28181.NewForwardSink(v.SSRC, v.Addr, setup, sinkId, v.Source)
if err != nil {
return
}
source.AddSink(sink)
log.Sugar.Infof("设置国标级联转发成功 ID: %s", sink.GetID())
response := struct {
Sink string `json:"sink"` //sink id
IP string `json:"ip"`
Port int `json:"port"`
}{Sink: stream.SinkId2String(sinkId), IP: stream.AppConfig.PublicIP, Port: port}
httpResponseOK(w, &response)
}