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
import (
"bytes"
"fmt"
"encoding/binary"
"encoding/hex"
"strings"
"unicode/utf16"
)
@ -194,8 +194,25 @@ func (g GapString) String(fill string) string {
return string(g.Bytes([]byte(fill)...))
}
func (g GapString) HexString(fill ...byte) string {
return hex.EncodeToString(g.Bytes(fill...))
func (g GapString) HexString() string {
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{
@ -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 {
out := new(strings.Builder)
skipping := false
glen := g.Length()
pos := 0
prev := []byte{}
for ; pos < glen; {
// Check for repeats
repeated := true
if (pos > 0) {
for i := 0; (i < 16) && (pos+i < glen); i += 1 {
if g.ValueAt(pos+i) != g.ValueAt(pos+i-16) {
repeated = false
break
}
}
if repeated {
if ! skipping {
fmt.Fprintln(out, "*")
skipping = true
}
pos += 16
continue
} else {
skipping = false
end := pos + 16
if end > glen {
end = glen
}
cur := g.Slice(pos, end)
curBytes := cur.Bytes()
if 0 == bytes.Compare(prev, curBytes) {
if ! skipping {
fmt.Fprintln(out, "*")
skipping = true
}
continue
}
// Output offset
fmt.Fprintf(out, "%08x ", pos)
// Output octet values
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, "%-50s", cur.HexString())
fmt.Fprintln(out, cur.Runes())
pos += cur.Length()
}
fmt.Fprintf(out, "%08x\n", pos)

View File

@ -1,8 +1,8 @@
package netshovel
import (
"encoding/hex"
"fmt"
"sort"
"strings"
"time"
"github.com/dirtbags/netshovel/gapstring"
@ -10,51 +10,72 @@ import (
type PacketFactory func()Packet
type Field struct {
key, value string
}
type Packet struct {
Name string
Opcode int
Description string
When time.Time
Payload gapstring.GapString
Fields map[string]string
Fields []Field
}
var never = time.Unix(0, 0)
func NewPacket() Packet {
return Packet{
Name: "Generic",
Opcode: -1,
Description: "Undefined",
When: never,
Payload: gapstring.GapString{},
Fields: map[string]string{},
Fields: []Field{},
}
}
func (pkt *Packet) Describe() string {
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.Name,
pkt.Opcode,
pkt.Description,
)
keys := make([]string, len(pkt.Fields))
i := 0
for k := range(pkt.Fields) {
keys[i] = k
i += 1
}
sort.Strings(keys)
for _, k := range keys {
fmt.Fprintf(out, " %s: %s\n", k, pkt.Fields[k])
for _, f := range(pkt.Fields) {
fmt.Fprintf(out, " %s: %s\n", f.key, f.value)
}
fmt.Fprint(out, pkt.Payload.Hexdump())
return out.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 (
"fmt"
"io"
"log"
"os"
"net/url"
"strings"
"time"
"github.com/dirtbags/netshovel/gapstring"
@ -11,9 +12,9 @@ import (
"github.com/google/gopacket/tcpassembly"
)
type WriteAtCloser interface {
io.WriterAt
io.WriteCloser
type NamedFile struct {
*os.File
Name string
}
type Utterance struct {
@ -58,10 +59,6 @@ func (stream *Stream) ReassemblyComplete() {
}
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"
if length == -1 {
if stream.pending.Data.Length() > 0 {
@ -111,3 +108,19 @@ func (stream *Stream) Describe(pkt Packet) string {
out.WriteString(pkt.Describe())
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
}