Files
lkm/stream/sink_utils.go
2025-05-31 21:06:33 +08:00

107 lines
2.6 KiB
Go

package stream
import (
"encoding/binary"
"fmt"
"github.com/lkmio/avformat/utils"
"github.com/lkmio/transport"
"net"
"net/url"
"strconv"
"time"
)
// SinkID IPV4使用uint64、IPV6使用string作为ID类型
type SinkID interface{}
type IPV4SinkID uint64
type IPV6SinkID string
func ipv4Addr2UInt64(ip uint32, port int) uint64 {
return (uint64(ip) << 32) | uint64(port)
}
// NetAddr2SinkID 根据网络地址生成SinkId IPV4使用一个uint64, IPV6使用String
func NetAddr2SinkID(addr net.Addr) SinkID {
network := addr.Network()
if "tcp" == network {
to4 := addr.(*net.TCPAddr).IP.To4()
var intIP uint32
if to4 != nil {
intIP = binary.BigEndian.Uint32(to4)
}
return ipv4Addr2UInt64(intIP, addr.(*net.TCPAddr).Port)
} else if "udp" == network {
to4 := addr.(*net.UDPAddr).IP.To4()
var intIP uint32
if to4 != nil {
intIP = binary.BigEndian.Uint32(to4)
}
return ipv4Addr2UInt64(intIP, addr.(*net.UDPAddr).Port)
}
return addr.String()
}
func SinkID2String(id SinkID) string {
if i, ok := id.(uint64); ok {
return strconv.FormatUint(i, 10)
}
return id.(string)
}
func GenerateUint64SinkID() SinkID {
return uint64(time.Now().UnixNano()&0xFFFFFFFF)<<32 | uint64(utils.RandomIntInRange(0, 0xFFFFFFFF))
}
func CreateSinkDisconnectionMessage(sink Sink) string {
return fmt.Sprintf("%s sink断开连接. id: %s", sink.GetProtocol(), sink.GetID())
}
func ExecuteSyncEventOnTransStreamPublisher(sourceId string, event func()) bool {
source := SourceManager.Find(sourceId)
if source != nil {
source.GetTransStreamPublisher().ExecuteSyncEvent(event)
return true
}
return false
}
func SubscribeStream(sink Sink, values url.Values) utils.HookState {
return SubscribeStreamWithOptions(sink, values, true, false)
}
func SubscribeStreamWithOptions(sink Sink, values url.Values, ready bool, timeout bool) utils.HookState {
sink.SetReady(ready)
sink.SetUrlValues(values)
_, state := PreparePlaySink(sink, timeout)
return state
}
func ForwardStream(protocol TransStreamProtocol, transport TransportType, sourceId string, values url.Values, remoteAddr string, manager transport.Manager) (Sink, int, error) {
//source := SourceManager.Find(sourceId)
//if source == nil {
// return nil, 0, fmt.Errorf("source %s 不存在", sourceId)
//}
sinkId := GenerateUint64SinkID()
var port int
sink, port, err := NewForwardSink(transport, protocol, sinkId, sourceId, remoteAddr, manager)
if err != nil {
return nil, 0, err
}
state := SubscribeStreamWithOptions(sink, values, true, true)
if utils.HookStateOK != state {
sink.Close()
return nil, 0, fmt.Errorf("failed to prepare play sink")
}
return sink, port, nil
}