rewrote how packing/unpacking is handled

This commit is contained in:
tigerbot 2017-03-22 15:03:58 -06:00
parent 8fb732e3b8
commit f163b4ec7d
3 changed files with 75 additions and 100 deletions

View File

@ -5,11 +5,13 @@ import (
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
"strings"
) )
const ( const (
packerV1 byte = 255 - 1 _ = iota // skip the iota value of 0
packerV2 byte = 255 - 2 packerV1 byte = 255 - iota
packerV2
) )
//Packer -- contains both header and data //Packer -- contains both header and data
@ -26,121 +28,95 @@ func NewPacker() (p *Packer) {
return return
} }
func splitHeader(header []byte, names []string) (map[string]string, error) {
parts := strings.Split(string(header), ",")
if p, n := len(parts), len(names); p > n {
return nil, fmt.Errorf("Header contains %d extra fields", p-n)
} else if p < n {
return nil, fmt.Errorf("Header missing fields %q", names[p:])
}
result := make(map[string]string, len(names))
for ind, key := range names {
result[key] = parts[ind]
}
return result, nil
}
//ReadMessage - //ReadMessage -
func ReadMessage(b []byte) (p *Packer, err error) { func ReadMessage(b []byte) (*Packer, error) {
fmt.Println("ReadMessage") fmt.Println("ReadMessage")
var pos int
err = nil // Detect protocol in use
// detect protocol in use
if b[0] == packerV1 { if b[0] == packerV1 {
p = NewPacker() // Separate the header and body using the header length in the second byte.
p := NewPacker()
header := b[2 : b[1]+2]
data := b[b[1]+2:]
// Handle Header Length // Handle the different parts of the header.
pos = pos + 1 parts, err := splitHeader(header, []string{"address family", "address", "port", "data length", "service"})
p.Header.HeaderLen = b[pos] if err != nil {
//handle address family
pos = pos + 1
end := bytes.IndexAny(b[pos:], ",")
if end == -1 {
err = fmt.Errorf("missing , while parsing address family")
return nil, err return nil, err
} }
bAddrFamily := b[pos : pos+end] if familyText := parts["address family"]; familyText == addressFamilyText[FamilyIPv4] {
if bytes.ContainsAny(bAddrFamily, addressFamilyText[FamilyIPv4]) {
p.Header.family = FamilyIPv4 p.Header.family = FamilyIPv4
} else if bytes.ContainsAny(bAddrFamily, addressFamilyText[FamilyIPv6]) { } else if familyText == addressFamilyText[FamilyIPv6] {
p.Header.family = FamilyIPv6 p.Header.family = FamilyIPv6
} else { } else {
err = fmt.Errorf("Address family not supported %d", bAddrFamily) return nil, fmt.Errorf("Address family %q not supported", familyText)
} }
//handle address p.Header.address = net.ParseIP(parts["address"])
pos = pos + end + 1 if p.Header.address == nil {
end = bytes.IndexAny(b[pos:], ",") return nil, fmt.Errorf("Invalid network address %q", parts["address"])
if end == -1 { } else if p.Header.Family() == FamilyIPv4 && p.Header.address.To4() == nil {
err = fmt.Errorf("missing , while parsing address") return nil, fmt.Errorf("Address %q is not in address family %s", parts["address"], p.Header.FamilyText())
return nil, err
}
p.Header.address = net.ParseIP(string(b[pos : pos+end]))
//handle import
pos = pos + end + 1
end = bytes.IndexAny(b[pos:], ",")
if end == -1 {
err = fmt.Errorf("missing , while parsing address")
return nil, err
} }
p.Header.Port, err = strconv.Atoi(string(b[pos : pos+end])) //handle port
if err != nil { if port, err := strconv.Atoi(parts["port"]); err != nil {
err = fmt.Errorf("error converting port %s", err) return nil, fmt.Errorf("Error converting port %q: %v", parts["port"], err)
} else if port <= 0 || port > 65535 {
return nil, fmt.Errorf("Port %d out of range", port)
} else {
p.Header.Port = port
} }
//handle data length //handle data length
pos = pos + end + 1 if dataLen, err := strconv.Atoi(parts["data length"]); err != nil {
end = bytes.IndexAny(b[pos:], ",") return nil, fmt.Errorf("Error converting data length %q: %v", parts["data length"], err)
if end == -1 { } else if dataLen != len(data) {
err = fmt.Errorf("missing , while parsing address") return nil, fmt.Errorf("Data length %d doesn't match received length %d", dataLen, len(data))
return nil, err
}
p.Data.DataLen, err = strconv.Atoi(string(b[pos : pos+end]))
if err != nil {
err = fmt.Errorf("error converting data length %s", err)
} }
//handle Service //handle Service
pos = pos + end + 1 p.Header.Service = parts["service"]
end = pos + int(p.Header.HeaderLen)
p.Header.Service = string(b[pos : p.Header.HeaderLen+2])
//handle payload //handle payload
pos = int(p.Header.HeaderLen + 2) p.Data.AppendBytes(data)
p.Data.AppendBytes(b[pos:]) return p, nil
} else {
err = fmt.Errorf("Version %d not supported", b[0:0])
} }
return return nil, fmt.Errorf("Version %d not supported", 255-b[0])
} }
//PackV1 -- Outputs version 1 of packer //PackV1 -- Outputs version 1 of packer
func (p *Packer) PackV1() (b bytes.Buffer) { func (p *Packer) PackV1() bytes.Buffer {
version := packerV1 header := strings.Join([]string{
p.Header.FamilyText(),
var headerBuf bytes.Buffer p.Header.AddressString(),
headerBuf.WriteString(p.Header.FamilyText()) strconv.Itoa(p.Header.Port),
headerBuf.WriteString(",") strconv.Itoa(p.Data.DataLen()),
headerBuf.Write([]byte(p.Header.Address().String())) p.Header.Service,
headerBuf.WriteString(",") }, ",")
headerBuf.WriteString(fmt.Sprintf("%d", p.Header.Port))
headerBuf.WriteString(",")
headerBuf.WriteString(fmt.Sprintf("%d", p.Data.buffer.Len()))
headerBuf.WriteString(",")
headerBuf.WriteString(p.Header.Service)
var metaBuf bytes.Buffer
metaBuf.WriteByte(version)
metaBuf.WriteByte(byte(headerBuf.Len()))
var buf bytes.Buffer var buf bytes.Buffer
buf.Write(metaBuf.Bytes()) buf.WriteByte(packerV1)
buf.Write(headerBuf.Bytes()) buf.WriteByte(byte(len(header)))
buf.Write(p.Data.buffer.Bytes()) buf.WriteString(header)
buf.Write(p.Data.Data())
//fmt.Println("header: ", headerBuf.String()) return buf
//fmt.Println("meta: ", metaBuf)
//fmt.Println("Data: ", p.Data.buffer)
//fmt.Println("Buffer: ", buf.Bytes())
//fmt.Println("Buffer: ", hex.Dump(buf.Bytes()))
//fmt.Printf("Buffer %s", buf.Bytes())
b = buf
return
} }

View File

@ -6,14 +6,11 @@ import (
//packerData -- Contains packer data //packerData -- Contains packer data
type packerData struct { type packerData struct {
buffer *bytes.Buffer buffer bytes.Buffer
DataLen int
} }
func newPackerData() (p *packerData) { func newPackerData() *packerData {
p = new(packerData) return new(packerData)
p.buffer = new(bytes.Buffer)
return
} }
func (p *packerData) AppendString(dataString string) (int, error) { func (p *packerData) AppendString(dataString string) (int, error) {
@ -28,3 +25,7 @@ func (p *packerData) AppendBytes(dataBytes []byte) (int, error) {
func (p *packerData) Data() []byte { func (p *packerData) Data() []byte {
return p.buffer.Bytes() return p.buffer.Bytes()
} }
func (p *packerData) DataLen() int {
return p.buffer.Len()
}

View File

@ -9,11 +9,10 @@ type addressFamily int
// packerHeader structure to hold our header information. // packerHeader structure to hold our header information.
type packerHeader struct { type packerHeader struct {
family addressFamily family addressFamily
address net.IP address net.IP
Port int Port int
Service string Service string
HeaderLen byte
} }
//Family -- ENUM for Address Family //Family -- ENUM for Address Family
@ -32,7 +31,6 @@ func newPackerHeader() (p *packerHeader) {
p.SetAddress("127.0.0.1") p.SetAddress("127.0.0.1")
p.Port = 65535 p.Port = 65535
p.Service = "na" p.Service = "na"
p.HeaderLen = 0
return return
} }