Start adding convenience
This commit is contained in:
parent
88f14b78d1
commit
620e16bbd0
|
@ -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
|
||||
end := pos + 16
|
||||
if end > glen {
|
||||
end = glen
|
||||
}
|
||||
}
|
||||
if repeated {
|
||||
cur := g.Slice(pos, end)
|
||||
curBytes := cur.Bytes()
|
||||
if 0 == bytes.Compare(prev, curBytes) {
|
||||
if ! skipping {
|
||||
fmt.Fprintln(out, "*")
|
||||
skipping = true
|
||||
}
|
||||
pos += 16
|
||||
continue
|
||||
} else {
|
||||
skipping = false
|
||||
}
|
||||
}
|
||||
|
||||
// Output offset
|
||||
fmt.Fprintf(out, "%08x ", pos)
|
||||
fmt.Fprintf(out, "%-50s", cur.HexString())
|
||||
fmt.Fprintln(out, cur.Runes())
|
||||
|
||||
// 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, "")
|
||||
pos += cur.Length()
|
||||
}
|
||||
fmt.Fprintf(out, "%08x\n", pos)
|
||||
|
||||
|
|
53
packet.go
53
packet.go
|
@ -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()))
|
||||
}
|
||||
|
|
29
stream.go
29
stream.go
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue