rewrote how packing/unpacking is handled
This commit is contained in:
parent
8fb732e3b8
commit
f163b4ec7d
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ type packerHeader struct {
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue