mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
116 lines
3.0 KiB
Go
116 lines
3.0 KiB
Go
//go:build linux
|
|
|
|
package scenario
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
|
|
"github.com/nezhahq/nezha/integration/agentcompat/internal/fixture"
|
|
)
|
|
|
|
var (
|
|
errLegacyFMInvalidFrame = errors.New("legacy FM invalid frame")
|
|
errLegacyFMUnexpected = errors.New("legacy FM unexpected frame")
|
|
)
|
|
|
|
type legacyFMRemoteError struct{}
|
|
|
|
func (legacyFMRemoteError) Error() string { return "legacy FM agent error" }
|
|
|
|
var errLegacyFMRemote = legacyFMRemoteError{}
|
|
|
|
const (
|
|
legacyFMListOp byte = 0x00
|
|
legacyFMDownloadOp byte = 0x01
|
|
legacyFMUploadOp byte = 0x02
|
|
)
|
|
|
|
type legacyFMEntry struct {
|
|
Name string
|
|
Dir bool
|
|
}
|
|
|
|
type legacyFMList struct {
|
|
Path string
|
|
Entries []legacyFMEntry
|
|
}
|
|
|
|
type legacyFMDownloadHeader struct {
|
|
Size uint64
|
|
}
|
|
|
|
func buildLegacyFMList(path fixture.AgentPath) []byte {
|
|
return append([]byte{legacyFMListOp}, []byte(path.String())...)
|
|
}
|
|
|
|
func buildLegacyFMUpload(path fixture.AgentPath, size uint64) []byte {
|
|
frame := make([]byte, 1+8+len(path.String()))
|
|
frame[0] = legacyFMUploadOp
|
|
binary.BigEndian.PutUint64(frame[1:9], size)
|
|
copy(frame[9:], path.String())
|
|
return frame
|
|
}
|
|
|
|
func buildLegacyFMDownload(path fixture.AgentPath) []byte {
|
|
return append([]byte{legacyFMDownloadOp}, []byte(path.String())...)
|
|
}
|
|
|
|
func parseLegacyFMList(frame []byte) (legacyFMList, error) {
|
|
if message, ok := parseLegacyFMError(frame); ok {
|
|
return legacyFMList{}, message
|
|
}
|
|
if len(frame) < 8 || !bytes.Equal(frame[:4], []byte("NZFN")) {
|
|
return legacyFMList{}, errLegacyFMInvalidFrame
|
|
}
|
|
pathSize := binary.BigEndian.Uint32(frame[4:8])
|
|
if pathSize == 0 || uint64(pathSize)+8 > uint64(len(frame)) {
|
|
return legacyFMList{}, errLegacyFMInvalidFrame
|
|
}
|
|
pathEnd := 8 + int(pathSize)
|
|
result := legacyFMList{Path: string(frame[8:pathEnd])}
|
|
for cursor := pathEnd; cursor < len(frame); {
|
|
if len(frame)-cursor < 2 {
|
|
return legacyFMList{}, errLegacyFMInvalidFrame
|
|
}
|
|
entrySize := int(frame[cursor+1])
|
|
if entrySize == 0 || cursor+2+entrySize > len(frame) || frame[cursor] > 1 {
|
|
return legacyFMList{}, errLegacyFMInvalidFrame
|
|
}
|
|
result.Entries = append(result.Entries, legacyFMEntry{
|
|
Name: string(frame[cursor+2 : cursor+2+entrySize]),
|
|
Dir: frame[cursor] == 1,
|
|
})
|
|
cursor += 2 + entrySize
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func parseLegacyFMDownload(frame []byte) (legacyFMDownloadHeader, error) {
|
|
if message, ok := parseLegacyFMError(frame); ok {
|
|
return legacyFMDownloadHeader{}, message
|
|
}
|
|
if len(frame) != 12 || !bytes.Equal(frame[:4], []byte("NZTD")) {
|
|
return legacyFMDownloadHeader{}, errLegacyFMInvalidFrame
|
|
}
|
|
return legacyFMDownloadHeader{Size: binary.BigEndian.Uint64(frame[4:12])}, nil
|
|
}
|
|
|
|
func parseLegacyFMError(frame []byte) (error, bool) {
|
|
if len(frame) < 4 || !bytes.Equal(frame[:4], []byte("NERR")) {
|
|
return nil, false
|
|
}
|
|
return errLegacyFMRemote, true
|
|
}
|
|
|
|
func requireLegacyFMMarker(frame []byte, marker string) error {
|
|
if message, ok := parseLegacyFMError(frame); ok {
|
|
return message
|
|
}
|
|
if !bytes.Equal(frame, []byte(marker)) {
|
|
return errLegacyFMUnexpected
|
|
}
|
|
return nil
|
|
}
|