Start adding convenience

This commit is contained in:
Neale Pickett 2018-07-23 23:48:14 +00:00
parent 88f14b78d1
commit 620e16bbd0
3 changed files with 108 additions and 80 deletions

View File

@ -1,9 +1,9 @@
package gapstring package gapstring
import ( import (
"bytes"
"fmt" "fmt"
"encoding/binary" "encoding/binary"
"encoding/hex"
"strings" "strings"
"unicode/utf16" "unicode/utf16"
) )
@ -194,8 +194,25 @@ func (g GapString) String(fill string) string {
return string(g.Bytes([]byte(fill)...)) return string(g.Bytes([]byte(fill)...))
} }
func (g GapString) HexString(fill ...byte) string { func (g GapString) HexString() string {
return hex.EncodeToString(g.Bytes(fill...)) out := new(strings.Builder)
glen := g.Length()
for i := 0; i < glen; i += 1 {
c := g.ValueAt(i)
if c == -1 {
out.WriteString("--")
} else {
// There's probably a faster way to do this. Do we care?
fmt.Fprintf(out, "%02x", c)
}
if i + 1 < glen {
out.WriteRune(' ')
if i % 8 == 7 {
out.WriteRune(' ')
}
}
}
return out.String()
} }
var fluffych = []rune{ var fluffych = []rune{
@ -216,70 +233,47 @@ var fluffych = []rune{
'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ', 'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩', 'α', 'ß', 'Γ', 'π', 'Σ', 'σ', 'µ', 'τ', 'Φ', 'Θ', 'Ω', 'δ', '∞', 'φ', 'ε', '∩',
'≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈', '°', '∀', '∃', '√', 'ⁿ', '²', '■', '¤', '≡', '±', '≥', '≤', '⌠', '⌡', '÷', '≈', '°', '∀', '∃', '√', 'ⁿ', '²', '■', '¤',
} }
func (g GapString) Runes() string {
out := new(strings.Builder)
glen := g.Length()
for i := 0; i < glen; i += 1 {
c := g.ValueAt(i)
if c == -1 {
out.WriteRune('<27>')
} else {
out.WriteRune(fluffych[c])
}
}
return out.String()
}
func (g GapString) Hexdump() string { func (g GapString) Hexdump() string {
out := new(strings.Builder) out := new(strings.Builder)
skipping := false skipping := false
glen := g.Length() glen := g.Length()
pos := 0 pos := 0
prev := []byte{}
for ; pos < glen; { for ; pos < glen; {
// Check for repeats // Check for repeats
repeated := true end := pos + 16
if (pos > 0) { if end > glen {
for i := 0; (i < 16) && (pos+i < glen); i += 1 { end = glen
if g.ValueAt(pos+i) != g.ValueAt(pos+i-16) {
repeated = false
break
} }
} cur := g.Slice(pos, end)
if repeated { curBytes := cur.Bytes()
if 0 == bytes.Compare(prev, curBytes) {
if ! skipping { if ! skipping {
fmt.Fprintln(out, "*") fmt.Fprintln(out, "*")
skipping = true skipping = true
} }
pos += 16
continue continue
} else {
skipping = false
}
} }
// Output offset
fmt.Fprintf(out, "%08x ", pos) fmt.Fprintf(out, "%08x ", pos)
fmt.Fprintf(out, "%-50s", cur.HexString())
fmt.Fprintln(out, cur.Runes())
// Output octet values pos += cur.Length()
for i := 0; i < 16; i += 1 {
if pos+i < glen {
c := g.ValueAt(pos+i)
if c == -1 {
fmt.Fprintf(out, "-- ")
} else {
fmt.Fprintf(out, "%02x ", c)
}
} else {
fmt.Fprintf(out, " ")
}
if i == 7 {
fmt.Fprintf(out, " ")
}
}
fmt.Fprintf(out, " ")
// Output octet glyphs
for i := 0; (i < 16) && (pos < glen); {
c := g.ValueAt(pos)
if c == -1 {
fmt.Fprintf(out, "<22>")
} else {
fmt.Fprintf(out, "%c", fluffych[c])
}
i += 1
pos += 1
}
// Output newline
fmt.Fprintln(out, "")
} }
fmt.Fprintf(out, "%08x\n", pos) fmt.Fprintf(out, "%08x\n", pos)

View File

@ -1,8 +1,8 @@
package netshovel package netshovel
import ( import (
"encoding/hex"
"fmt" "fmt"
"sort"
"strings" "strings"
"time" "time"
"github.com/dirtbags/netshovel/gapstring" "github.com/dirtbags/netshovel/gapstring"
@ -10,51 +10,72 @@ import (
type PacketFactory func()Packet type PacketFactory func()Packet
type Field struct {
key, value string
}
type Packet struct { type Packet struct {
Name string Name string
Opcode int Opcode int
Description string Description string
When time.Time When time.Time
Payload gapstring.GapString Payload gapstring.GapString
Fields map[string]string Fields []Field
} }
var never = time.Unix(0, 0) var never = time.Unix(0, 0)
func NewPacket() Packet { func NewPacket() Packet {
return Packet{ return Packet{
Name: "Generic",
Opcode: -1, Opcode: -1,
Description: "Undefined", Description: "Undefined",
When: never, When: never,
Payload: gapstring.GapString{}, Payload: gapstring.GapString{},
Fields: map[string]string{}, Fields: []Field{},
} }
} }
func (pkt *Packet) Describe() string { func (pkt *Packet) Describe() string {
out := new(strings.Builder) out := new(strings.Builder)
fmt.Fprintf(out, " %s %s %d: %s\n", fmt.Fprintf(out, " %s Opcode %d: %s\n",
pkt.When.UTC().Format(time.RFC3339Nano), pkt.When.UTC().Format(time.RFC3339Nano),
pkt.Name,
pkt.Opcode, pkt.Opcode,
pkt.Description, pkt.Description,
) )
keys := make([]string, len(pkt.Fields))
i := 0 for _, f := range(pkt.Fields) {
for k := range(pkt.Fields) { fmt.Fprintf(out, " %s: %s\n", f.key, f.value)
keys[i] = k
i += 1
}
sort.Strings(keys)
for _, k := range keys {
fmt.Fprintf(out, " %s: %s\n", k, pkt.Fields[k])
} }
fmt.Fprint(out, pkt.Payload.Hexdump()) fmt.Fprint(out, pkt.Payload.Hexdump())
return out.String() return out.String()
} }
func (pkt *Packet) Set(key, value string) { func (pkt *Packet) Set(key, value string) {
pkt.Fields[key] = value pkt.Fields = append(pkt.Fields, Field{key, value})
}
func (pkt *Packet) SetString(key, value string) {
pkt.Set(key, fmt.Sprintf("%#v", value))
}
func (pkt *Packet) SetInt(key string, value int) {
pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
}
func (pkt *Packet) SetUint(key string, value uint) {
pkt.Set(key, fmt.Sprintf("%d == 0x%x", value, value))
}
func (pkt *Packet) SetUint32(key string, value uint32) {
pkt.Set(key, fmt.Sprintf("%d == 0x%04x", value, value))
}
func (pkt *Packet) SetBytes(key string, value []byte) {
pkt.Set(key, hex.EncodeToString(value))
}
func (pkt *Packet) SetGapString(key string, value gapstring.GapString) {
pkt.Set(key, fmt.Sprintf("%s %s", value.HexString(), value.Runes()))
} }

View File

@ -3,7 +3,8 @@ package netshovel
import ( import (
"fmt" "fmt"
"io" "io"
"log" "os"
"net/url"
"strings" "strings"
"time" "time"
"github.com/dirtbags/netshovel/gapstring" "github.com/dirtbags/netshovel/gapstring"
@ -11,9 +12,9 @@ import (
"github.com/google/gopacket/tcpassembly" "github.com/google/gopacket/tcpassembly"
) )
type WriteAtCloser interface { type NamedFile struct {
io.WriterAt *os.File
io.WriteCloser Name string
} }
type Utterance struct { type Utterance struct {
@ -58,10 +59,6 @@ func (stream *Stream) ReassemblyComplete() {
} }
func (stream *Stream) Read(length int) (Utterance, error) { func (stream *Stream) Read(length int) (Utterance, error) {
if length > 0x100000 {
log.Fatalf("FATAL: Trying to read 0x%x octets", length)
}
// Special case: length=-1 means "give me the next utterance" // Special case: length=-1 means "give me the next utterance"
if length == -1 { if length == -1 {
if stream.pending.Data.Length() > 0 { if stream.pending.Data.Length() > 0 {
@ -111,3 +108,19 @@ func (stream *Stream) Describe(pkt Packet) string {
out.WriteString(pkt.Describe()) out.WriteString(pkt.Describe())
return out.String() return out.String()
} }
func (stream *Stream) CreateFile(when time.Time, path string) (NamedFile, error) {
name := fmt.Sprintf(
"xfer/%s,%sp%s,%sp%s,%s",
when.UTC().Format(time.RFC3339Nano),
stream.Net.Src().String(), stream.Transport.Src().String(),
stream.Net.Dst().String(), stream.Transport.Dst().String(),
url.PathEscape(path),
)
f, err := os.Create(name)
outf := NamedFile{
File: f,
Name: name,
}
return outf, err
}