From 8f12b071562a07b645bb21e4e2ffa4b99390d66a Mon Sep 17 00:00:00 2001 From: Jason Playne Date: Mon, 6 Nov 2023 20:30:49 +0800 Subject: [PATCH] Bug: use a copy of the data rather than the address of the loop var (which is always the same) A few yoda to not yoda changes increasing CPR max time diff to 10s from 1.5s --- lib/producer/beast.go | 122 ++++++++++++++++------------------- lib/producer/common.go | 2 +- lib/tracker/beast/main.go | 5 +- lib/tracker/cpr.go | 2 +- lib/tracker/input.go | 6 +- lib/tracker/mode_s/decode.go | 2 +- lib/tracker/mode_s/frame.go | 2 +- 7 files changed, 67 insertions(+), 74 deletions(-) diff --git a/lib/producer/beast.go b/lib/producer/beast.go index baab3622..6610de17 100644 --- a/lib/producer/beast.go +++ b/lib/producer/beast.go @@ -13,7 +13,7 @@ const tokenBufLen = 50 func (p *Producer) beastScanner(scan *bufio.Scanner) error { lastTimeStamp := time.Duration(0) for scan.Scan() { - msg := scan.Bytes() + msg := bytes.Clone(scan.Bytes()) frame, err := beast.NewFrame(msg, false) if nil != err { continue @@ -39,77 +39,69 @@ func (p *Producer) beastScanner(scan *bufio.Scanner) error { } // ScanBeast is a splitter for BEAST format messages -func ScanBeast() func(data []byte, atEOF bool) (int, []byte, error) { - // slices are pointers in themselves - // let GoLang's garbage collection collect old buffers when they are no longer referenced - //var tokenBuf []byte - //var tokenBufIdx uint - //var l sync.Mutex - - return func(data []byte, atEOF bool) (int, []byte, error) { - if atEOF && len(data) == 0 { - return 0, nil, nil - } - - // skip until we get our first 0x1A (message start) - i := bytes.IndexByte(data, 0x1A) - if -1 == i || len(data) < i+11 { - // we do not even have the smallest message, let's get some more data - return 0, nil, nil - } - // byte 2 is our message type, so it tells us how long this message is - msgLen := 0 - switch data[i+1] { - case 0x31: - // mode-ac 11 bytes (2+8) - // 1(esc), 1(type), 6(mlat), 1(signal), 2(mode-ac) - msgLen = 11 - case 0x32: - // mode-s short 16 bytes - // 1(esc), 1(type), 6(mlat), 1(signal), 7(mode-s short) - msgLen = 16 - case 0x33: - // mode-s long 23 bytes - // 1(esc), 1(type), 6(mlat), 1(signal), 14(mode-s extended squitter) - msgLen = 23 - case 0x34: - // Config Settings and Stats - // 1(esc), 1(type), 6(mlat), 1(unused), (1)DIP Config, (1)timestamp error ticks - msgLen = 11 - case 0x1A: - // found an escaped 0x1A, skip that too - return i + 2, nil, nil +func ScanBeast(data []byte, atEOF bool) (int, []byte, error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } - default: - // unknown? assume we got an out of sequence and skip - return i + 1, nil, nil - } - bufLen := len(data) - i - //println("type", data[i+1], "input len", bufLen, "msg len",msgLen) - if bufLen >= tokenBufLen { - // we have enough in our buffer - // account for double escapes - bufferAdvance := i + msgLen + // skip until we get our first 0x1A (message start) + i := bytes.IndexByte(data, 0x1A) + if -1 == i || len(data) < i+11 { + // we do not even have the smallest message, let's get some more data + return 0, nil, nil + } + // byte 2 is our message type, so it tells us how long this message is + msgLen := 0 + switch data[i+1] { + case 0x31: + // mode-ac 11 bytes (2+8) + // 1(esc), 1(type), 6(mlat), 1(signal), 2(mode-ac) + msgLen = 11 + case 0x32: + // mode-s short 16 bytes + // 1(esc), 1(type), 6(mlat), 1(signal), 7(mode-s short) + msgLen = 16 + case 0x33: + // mode-s long 23 bytes + // 1(esc), 1(type), 6(mlat), 1(signal), 14(mode-s extended squitter) + msgLen = 23 + case 0x34: + // Config Settings and Stats + // 1(esc), 1(type), 6(mlat), 1(unused), (1)DIP Config, (1)timestamp error ticks + msgLen = 11 + case 0x1A: + // found an escaped 0x1A, skip that too + return i + 2, nil, nil - token := [tokenBufLen]byte{} + default: + // unknown? assume we got an out of sequence and skip + return i + 1, nil, nil + } + bufLen := len(data) - i + //println("type", data[i+1], "input len", bufLen, "msg len",msgLen) + if bufLen >= tokenBufLen { + // we have enough in our buffer + // account for double escapes + bufferAdvance := i + msgLen - dataIndex := i // start at the /0x1a - tokenIndex := 0 - for tokenIndex < msgLen && dataIndex < i+tokenBufLen { - token[tokenIndex] = data[dataIndex] + token := [tokenBufLen]byte{} - // if the next byte is an escaped 0x1A, jump it - if data[dataIndex] == 0x1A && data[dataIndex+1] == 0x1A { // skip over the second - bufferAdvance++ - dataIndex++ - } + dataIndex := i // start at the /0x1a + tokenIndex := 0 + for tokenIndex < msgLen && dataIndex < i+tokenBufLen { + token[tokenIndex] = data[dataIndex] + // if the next byte is an escaped 0x1A, jump it + if data[dataIndex] == 0x1A && data[dataIndex+1] == 0x1A { // skip over the second + bufferAdvance++ dataIndex++ - tokenIndex++ } - return bufferAdvance, token[0:msgLen], nil + + dataIndex++ + tokenIndex++ } - // we want more data! - return 0, nil, nil + return bufferAdvance, token[0:msgLen], nil } + // we want more data! + return 0, nil, nil } diff --git a/lib/producer/common.go b/lib/producer/common.go index 3f0d70b6..e57e7407 100644 --- a/lib/producer/common.go +++ b/lib/producer/common.go @@ -198,7 +198,7 @@ func WithType(producerType int) Option { p.splitter = bufio.ScanLines case Beast: p.producerType = producerType - p.splitter = ScanBeast() + p.splitter = ScanBeast default: p.log.Error().Msgf("Unknown Producer Type") } diff --git a/lib/tracker/beast/main.go b/lib/tracker/beast/main.go index 9354c89b..866cd9c7 100644 --- a/lib/tracker/beast/main.go +++ b/lib/tracker/beast/main.go @@ -63,10 +63,9 @@ func (f *Frame) Decode() error { f.hasDecoded = true } return err - } else { - f.hasDecoded = true - return mode_s.ErrNoOp } + f.hasDecoded = true + return mode_s.ErrNoOp } func (f *Frame) TimeStamp() time.Time { diff --git a/lib/tracker/cpr.go b/lib/tracker/cpr.go index d7242214..0fc43779 100644 --- a/lib/tracker/cpr.go +++ b/lib/tracker/cpr.go @@ -204,7 +204,7 @@ func (cpr *CprLocation) computeLongitudeZone() error { func (cpr *CprLocation) checkFrameTiming() error { d := cpr.time1.Sub(cpr.time0) tt := math.Abs(float64(d.Milliseconds())) - if tt > 1500 { // allow for some network jitter + time of flight jitter + if tt > 10_000 { // allow for some network jitter + time of flight jitter return errors.New("unable to decode this CPR Pair. they are too far apart in time") } return nil diff --git a/lib/tracker/input.go b/lib/tracker/input.go index e9c09a7d..e0fd9eb4 100644 --- a/lib/tracker/input.go +++ b/lib/tracker/input.go @@ -99,8 +99,10 @@ func (t *Tracker) Finish() { } func (t *Tracker) EventListener(eventSource EventMaker, waiter *sync.WaitGroup) { + // todo: remove this level of indirection! for e := range eventSource.Listen() { - t.decodingQueue <- &e + foobar := *(&e) + t.decodingQueue <- &foobar } waiter.Done() t.log.Debug().Msg("Done with Event Source") @@ -208,6 +210,7 @@ func (t *Tracker) decodeQueue() { if nil != t.stats.decodedFrames { t.stats.decodedFrames.Inc() } + frame := f.Frame() err := frame.Decode() if nil != err { @@ -232,7 +235,6 @@ func (t *Tracker) decodeQueue() { switch typeFrame := frame.(type) { case *beast.Frame: - plane.HandleModeSFrame(typeFrame.AvrFrame(), f.Source().RefLat, f.Source().RefLon) plane.setSignalLevel(typeFrame.SignalRssi()) case *mode_s.Frame: diff --git a/lib/tracker/mode_s/decode.go b/lib/tracker/mode_s/decode.go index 816425ec..95bbd08e 100644 --- a/lib/tracker/mode_s/decode.go +++ b/lib/tracker/mode_s/decode.go @@ -259,7 +259,7 @@ func (f *Frame) parseRawToMessage() error { frameLen := len(f.raw) // cheap bitwise even number check! - if 0 != (frameLen & 1) { + if (frameLen & 1) != 0 { return fmt.Errorf("frame is an odd length (%d), cannot decode unless length is even", frameLen) } diff --git a/lib/tracker/mode_s/frame.go b/lib/tracker/mode_s/frame.go index 5ee97fcf..2477111b 100644 --- a/lib/tracker/mode_s/frame.go +++ b/lib/tracker/mode_s/frame.go @@ -598,7 +598,7 @@ func (f *Frame) RawString() string { if nil == f { return "" } - if f.fromBytes && "" == f.raw { + if f.fromBytes && f.raw == "" { // we need to convert f.raw = fmt.Sprintf("%X", f.message) }