Refactor and simplify package structure and interfaces.
Reorganize code by removing unused files, restructuring package organization, and updating import references to new paths. This simplifies handling of smart and protocol-related operations, improves maintainability, and eliminates redundancy.
This commit is contained in:
167
pkg/smart/channel.go
Normal file
167
pkg/smart/channel.go
Normal file
@ -0,0 +1,167 @@
|
||||
package smart
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
|
||||
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
|
||||
"gitea.unprism.ru/KRBL/n9m/v2/pkg/utils"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
length = 6
|
||||
)
|
||||
|
||||
func NewSmartChannelPackage(conn net.Conn, mainSmartPackage *SmartPackage) (*SmartChannelPackage, error) {
|
||||
pack := NewSmartPackage(conn)
|
||||
pack.pack.Payload.Session = mainSmartPackage.pack.Payload.Session
|
||||
|
||||
channelName, err := registerChannelHandles(pack)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
smartChannelPackage := &SmartChannelPackage{
|
||||
pack: pack,
|
||||
mainPack: mainSmartPackage,
|
||||
|
||||
channelName: channelName,
|
||||
|
||||
mutex: sync.RWMutex{},
|
||||
ssrc: make(map[uint16][]func([]byte) error),
|
||||
}
|
||||
|
||||
pack.AddPayloadHandler(protocol.PayloadTypeLive, smartChannelPackage.handleLiveVideo)
|
||||
|
||||
return smartChannelPackage, nil
|
||||
}
|
||||
|
||||
func (channelPack *SmartChannelPackage) Run() error {
|
||||
for {
|
||||
if err := channelPack.pack.Handle(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (channelPack *SmartChannelPackage) GetChannelName() string {
|
||||
return channelPack.channelName
|
||||
}
|
||||
|
||||
func (channelPack *SmartChannelPackage) AddLiveSource(ssrc uint16, source func([]byte) error) {
|
||||
channelPack.mutex.Lock()
|
||||
defer channelPack.mutex.Unlock()
|
||||
|
||||
channelPack.ssrc[ssrc] = append(channelPack.ssrc[ssrc], source)
|
||||
}
|
||||
|
||||
func (channelPack *SmartChannelPackage) handleLiveVideo(sPack *SmartPackage, pack protocol.Package) error {
|
||||
channelPack.mutex.RLock()
|
||||
|
||||
sources, ok := channelPack.ssrc[uint16(pack.SSRC)]
|
||||
|
||||
if !ok || len(sources) == 0 {
|
||||
channelPack.mutex.RUnlock()
|
||||
|
||||
var request = models.MediaStreamModelControlStreamRequest{
|
||||
PayloadType: protocol.PayloadTypeLive,
|
||||
SSRC: uint16(pack.SSRC),
|
||||
StreamName: channelPack.channelName,
|
||||
Command: models.MediaStreamCommandStop,
|
||||
}
|
||||
|
||||
pack.PayloadType = protocol.PayloadTypeData
|
||||
pack.Payload.Module = "MEDIASTREAMMODEL"
|
||||
pack.Payload.Operation = "CONTROLSTREAM"
|
||||
pack.SetParameters(request)
|
||||
|
||||
if _, err := channelPack.mainPack.Write(pack.PackPackage()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var errorMask = map[int]bool{}
|
||||
|
||||
for i, source := range sources {
|
||||
if err := source(pack.RawPayload); err != nil {
|
||||
errorMask[i] = true
|
||||
}
|
||||
}
|
||||
|
||||
channelPack.mutex.RUnlock()
|
||||
|
||||
if len(errorMask) > 0 {
|
||||
newSources := make([]func([]byte) error, 0, len(sources))
|
||||
|
||||
for i, source := range sources {
|
||||
if !errorMask[i] {
|
||||
newSources = append(newSources, source)
|
||||
}
|
||||
}
|
||||
|
||||
channelPack.mutex.Lock()
|
||||
channelPack.ssrc[uint16(pack.SSRC)] = newSources
|
||||
channelPack.mutex.Unlock()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerChannelHandles(pack *SmartPackage) (string, error) {
|
||||
res := make(chan error, 1)
|
||||
|
||||
pack.AddJSONHandler("CERTIFICATE", "CREATESTREAM", func(smartPackage *SmartPackage, p protocol.Package) error {
|
||||
var params models.CertificateCreateStreamResponse
|
||||
|
||||
if err := p.GetResponseAs(¶ms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if params.ErrorCode != 0 {
|
||||
res <- errors.New(params.ErrorCause)
|
||||
} else {
|
||||
res <- nil
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
channelName := utils.RandomString(length, charset)
|
||||
|
||||
var request = models.CertificateCreateStreamRequest{
|
||||
StreamName: channelName,
|
||||
}
|
||||
|
||||
pack.pack.Payload.Module = "CERTIFICATE"
|
||||
pack.pack.Payload.Operation = "CREATESTREAM"
|
||||
pack.pack.SetParameters(request)
|
||||
|
||||
pack.Write(pack.pack.PackPackage())
|
||||
|
||||
for {
|
||||
if err := pack.Handle(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
select {
|
||||
case err := <-res:
|
||||
close(res)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pack.AddJSONHandler("CERTIFICATE", "CREATESTREAM", func(smartPackage *SmartPackage, p protocol.Package) error {
|
||||
return errors.New("stream already exists")
|
||||
})
|
||||
|
||||
return channelName, nil
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
33
pkg/smart/scheme.go
Normal file
33
pkg/smart/scheme.go
Normal file
@ -0,0 +1,33 @@
|
||||
package smart
|
||||
|
||||
import (
|
||||
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
|
||||
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type ProcessFunc func(*SmartPackage, protocol.Package) error
|
||||
type AlarmProcessFunc func(*SmartPackage, protocol.Package, models.SendAlarmInfoResponse) error
|
||||
|
||||
type SmartPackage struct {
|
||||
pack protocol.Package
|
||||
|
||||
conn net.Conn
|
||||
buff []byte
|
||||
|
||||
payloadProcess map[protocol.PayloadType]ProcessFunc
|
||||
jsonProcess map[string]ProcessFunc
|
||||
alarmProcess map[protocol.AlarmType]AlarmProcessFunc
|
||||
Storage map[string]interface{}
|
||||
}
|
||||
|
||||
type SmartChannelPackage struct {
|
||||
pack *SmartPackage
|
||||
mainPack *SmartPackage
|
||||
|
||||
channelName string
|
||||
|
||||
mutex sync.RWMutex
|
||||
ssrc map[uint16][]func([]byte) error
|
||||
}
|
144
pkg/smart/smart.go
Normal file
144
pkg/smart/smart.go
Normal file
@ -0,0 +1,144 @@
|
||||
package smart
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
|
||||
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
|
||||
"net"
|
||||
)
|
||||
|
||||
type notFoundError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func (e *notFoundError) Error() string {
|
||||
return fmt.Sprintf("not found %s", e.message)
|
||||
}
|
||||
|
||||
func NewSmartPackage(conn net.Conn) *SmartPackage {
|
||||
return &SmartPackage{
|
||||
pack: protocol.Package{},
|
||||
conn: conn,
|
||||
buff: make([]byte, 1024),
|
||||
payloadProcess: make(map[protocol.PayloadType]ProcessFunc),
|
||||
jsonProcess: make(map[string]ProcessFunc),
|
||||
alarmProcess: make(map[protocol.AlarmType]AlarmProcessFunc),
|
||||
Storage: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) AddPayloadHandler(payloadType protocol.PayloadType, processFunc ProcessFunc) {
|
||||
pack.payloadProcess[payloadType] = processFunc
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) AddJSONHandler(module, operation string, processFunc ProcessFunc) {
|
||||
pack.jsonProcess[fmt.Sprintf("%s:%s", module, operation)] = processFunc
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) AddAlarmHandler(alarmType protocol.AlarmType, processFunc AlarmProcessFunc) {
|
||||
pack.alarmProcess[alarmType] = processFunc
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) handleAlarm() (err error) {
|
||||
if !(pack.pack.PayloadType == protocol.PayloadTypeData && pack.pack.Payload.Module == "EVEM" && pack.pack.Payload.Operation == "SENDALARMINFO") {
|
||||
return fmt.Errorf("invalid payload type or operation for alarm handling")
|
||||
}
|
||||
|
||||
var params models.SendAlarmInfoParameters
|
||||
if err = pack.pack.GetParametersAs(¶ms); err != nil {
|
||||
return fmt.Errorf("invalid payload")
|
||||
}
|
||||
|
||||
var processFunc AlarmProcessFunc
|
||||
var ok bool
|
||||
if processFunc, ok = pack.alarmProcess[params.AlarmType]; !ok {
|
||||
return ¬FoundError{
|
||||
message: fmt.Sprintf("alarm %d", params.AlarmType),
|
||||
}
|
||||
}
|
||||
|
||||
var response models.SendAlarmInfoResponse
|
||||
|
||||
response.ErrorCode = 0
|
||||
response.AlarmType = params.AlarmType
|
||||
response.CommandType = params.CommandType
|
||||
response.AlarmUID = params.AlarmUID
|
||||
response.NumberOfRestarts = params.NumberOfRestarts
|
||||
response.InstructionSerial = params.InstructionSerial
|
||||
|
||||
return processFunc(pack, pack.pack, response)
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) handleJson() (err error) {
|
||||
if pack.pack.PayloadType != protocol.PayloadTypeData {
|
||||
return fmt.Errorf("invalid json payload type")
|
||||
}
|
||||
|
||||
var nfErr *notFoundError
|
||||
if err = pack.handleAlarm(); err == nil || errors.As(err, &nfErr) {
|
||||
return
|
||||
}
|
||||
|
||||
var processFunc ProcessFunc
|
||||
var ok bool
|
||||
var key = fmt.Sprintf("%s:%s", pack.pack.Payload.Module, pack.pack.Payload.Operation)
|
||||
if processFunc, ok = pack.jsonProcess[key]; !ok {
|
||||
return ¬FoundError{
|
||||
message: fmt.Sprintf("json %s", key),
|
||||
}
|
||||
}
|
||||
|
||||
return processFunc(pack, pack.pack)
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) handle() (err error) {
|
||||
var nfErr *notFoundError
|
||||
if err = pack.handleJson(); err == nil || errors.As(err, &nfErr) {
|
||||
return
|
||||
}
|
||||
|
||||
var processFunc ProcessFunc
|
||||
var ok bool
|
||||
if processFunc, ok = pack.payloadProcess[pack.pack.PayloadType]; !ok {
|
||||
return ¬FoundError{
|
||||
message: fmt.Sprintf("payload type %d", pack.pack.PayloadType),
|
||||
}
|
||||
}
|
||||
|
||||
return processFunc(pack, pack.pack)
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) handleLoop() (err error) {
|
||||
for pack.pack.ReadPackage() {
|
||||
if err = pack.handle(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) Handle() (err error) {
|
||||
if err = pack.handleLoop(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var rn int
|
||||
|
||||
if rn, err = pack.conn.Read(pack.buff); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pack.pack.AddToAccum(pack.buff[:rn])
|
||||
|
||||
return pack.handleLoop()
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) GetPackage() protocol.Package {
|
||||
return pack.pack
|
||||
}
|
||||
|
||||
func (pack *SmartPackage) Write(data []byte) (int, error) {
|
||||
return pack.conn.Write(data)
|
||||
}
|
Reference in New Issue
Block a user