func (f *Frame) Meta() *FrameMeta {
	return &f.meta
}
Meta returns the frame metadata, a gopacket.Flow
this allows the user to determine if a Frame is inbound or outbound.
package zanarkand
import (
	"bufio"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"net"
	"time"
	"github.com/google/gopacket"
)
const frameHeaderLength = 40
const frameMagicLE uint64 = 0xE2465DFF41A05252
const (
	FrameIngress FlowDirection = 1
	FrameEgress  FlowDirection = 2
)
type FlowDirection int
type Frame struct {
	Magic      uint64    `json:"-"`               
	Timestamp  time.Time `json:"-"`               
	Length     uint32    `json:"size"`            
	Connection uint16    `json:"connectionType"`  
	Count      uint16    `json:"count"`           
	reserved1  byte       
	Compressed bool      `json:"compressed"`  
	reserved2  uint32     
	reserved3  uint16     
	Body       []byte    `json:"-"`
	meta FrameMeta
}
type FrameMeta struct {
	Flow gopacket.Flow
}
func (f *Frame) Decode(p []byte) {
	f.Magic = binary.LittleEndian.Uint64(p[0:8])
	msec := time.Duration(binary.LittleEndian.Uint64(p[16:24])) * time.Millisecond
	f.Timestamp = time.Unix(0, 0).Add(msec)
	f.Length = binary.LittleEndian.Uint32(p[24:28])
	f.Connection = binary.LittleEndian.Uint16(p[28:30])
	f.Compressed = p[33] != 0
	f.Count = binary.LittleEndian.Uint16(p[30:32])
	f.Body = p[frameHeaderLength:f.Length]
}
func (f *Frame) Direction() FlowDirection {
	src, dst := f.meta.Flow.Endpoints()
	srcIP := net.ParseIP(src.String())
	dstIP := net.ParseIP(dst.String())
	if isPrivate(dstIP) && !isPrivate(srcIP) {
		return FrameIngress
	}
	if isPrivate(srcIP) && !isPrivate(dstIP) {
		return FrameEgress
	}
	return 0
}
func (f *Frame) MarshalJSON() ([]byte, error) {
	type Alias Frame
	data := make([]int, len(f.Body))
	for i, b := range f.Body {
		data[i] = int(b)
	}
	return json.Marshal(&struct {
		Data      []int `json:"data"`
		Timestamp int32 `json:"timestamp"`
		*Alias
	}{
		Data:      data,
		Timestamp: int32(f.Timestamp.Unix()),
		Alias:     (*Alias)(f),
	})
}