k3s/vendor/github.com/bronze1man/goStrongswanVici/msg.go
2019-09-27 18:33:04 -07:00

360 lines
7.3 KiB
Go

package goStrongswanVici
import (
"bufio"
"bytes"
"encoding/binary"
"fmt"
"io"
"strconv"
)
type segmentType byte
const (
stCMD_REQUEST segmentType = 0
stCMD_RESPONSE = 1
stCMD_UNKNOWN = 2
stEVENT_REGISTER = 3
stEVENT_UNREGISTER = 4
stEVENT_CONFIRM = 5
stEVENT_UNKNOWN = 6
stEVENT = 7
)
func (t segmentType) hasName() bool {
switch t {
case stCMD_REQUEST, stEVENT_REGISTER, stEVENT_UNREGISTER, stEVENT:
return true
}
return false
}
func (t segmentType) isValid() bool {
switch t {
case stCMD_REQUEST, stCMD_RESPONSE, stCMD_UNKNOWN, stEVENT_REGISTER,
stEVENT_UNREGISTER, stEVENT_CONFIRM, stEVENT_UNKNOWN, stEVENT:
return true
}
return false
}
func (t segmentType) hasMsg() bool {
switch t {
case stCMD_REQUEST, stCMD_RESPONSE, stEVENT:
return true
}
return false
}
type elementType byte
const (
etSECTION_START elementType = 1
etSECTION_END = 2
etKEY_VALUE = 3
etLIST_START = 4
etLIST_ITEM = 5
etLIST_END = 6
)
type segment struct {
typ segmentType
name string
msg map[string]interface{}
}
//msg 在内部以下列3种类型表示(降低复杂度)
// string
// map[string]interface{}
// []string
func writeSegment(w io.Writer, msg segment) (err error) {
if !msg.typ.isValid() {
return fmt.Errorf("[writeSegment] msg.typ %d not defined", msg.typ)
}
buf := &bytes.Buffer{}
buf.WriteByte(byte(msg.typ))
//name
if msg.typ.hasName() {
err = writeString1(buf, msg.name)
if err != nil {
fmt.Printf("error returned from writeString1i \n")
return
}
}
if msg.typ.hasMsg() {
err = writeMap(buf, msg.msg)
if err != nil {
fmt.Printf("error retruned from writeMap \n")
return
}
}
//写长度
err = binary.Write(w, binary.BigEndian, uint32(buf.Len()))
if err != nil {
fmt.Printf("[writeSegment] error writing to binary \n")
return
}
_, err = buf.WriteTo(w)
if err != nil {
fmt.Printf("[writeSegment] error writing to buffer \n")
return
}
return nil
}
func readSegment(inR io.Reader) (msg segment, err error) {
//长度
var length uint32
err = binary.Read(inR, binary.BigEndian, &length)
if err != nil {
return
}
r := bufio.NewReader(&io.LimitedReader{
R: inR,
N: int64(length),
})
//类型
c, err := r.ReadByte()
if err != nil {
return
}
msg.typ = segmentType(c)
if !msg.typ.isValid() {
return msg, fmt.Errorf("[readSegment] msg.typ %d not defined", msg.typ)
}
if msg.typ.hasName() {
msg.name, err = readString1(r)
if err != nil {
return
}
}
if msg.typ.hasMsg() {
msg.msg, err = readMap(r, true)
if err != nil {
return
}
}
return
}
//一个字节长度的字符串
func writeString1(w *bytes.Buffer, s string) (err error) {
length := len(s)
if length > 255 {
return fmt.Errorf("[writeString1] length>255")
}
w.WriteByte(byte(length))
w.WriteString(s)
return
}
func readString1(r *bufio.Reader) (s string, err error) {
length, err := r.ReadByte()
if err != nil {
return
}
buf := make([]byte, length)
_, err = io.ReadFull(r, buf)
if err != nil {
return
}
return string(buf), nil
}
//两个字节长度的字符串
func writeString2(w *bytes.Buffer, s string) (err error) {
length := len(s)
if length > 65535 {
return fmt.Errorf("[writeString2] length>65535")
}
binary.Write(w, binary.BigEndian, uint16(length))
w.WriteString(s)
return
}
func readString2(r io.Reader) (s string, err error) {
var length uint16
err = binary.Read(r, binary.BigEndian, &length)
if err != nil {
return
}
buf := make([]byte, length)
_, err = io.ReadFull(r, buf)
if err != nil {
return
}
return string(buf), nil
}
func writeKeyMap(w *bytes.Buffer, name string, msg map[string]interface{}) (err error) {
w.WriteByte(byte(etSECTION_START))
err = writeString1(w, name)
if err != nil {
return
}
writeMap(w, msg)
w.WriteByte(byte(etSECTION_END))
return nil
}
func writeKeyList(w *bytes.Buffer, name string, msg []string) (err error) {
w.WriteByte(byte(etLIST_START))
err = writeString1(w, name)
if err != nil {
return
}
for _, s := range msg {
w.WriteByte(byte(etLIST_ITEM))
err = writeString2(w, s)
if err != nil {
return
}
}
w.WriteByte(byte(etLIST_END))
return nil
}
func writeKeyString(w *bytes.Buffer, name string, msg string) (err error) {
w.WriteByte(byte(etKEY_VALUE))
err = writeString1(w, name)
if err != nil {
return
}
err = writeString2(w, msg)
return
}
func writeMap(w *bytes.Buffer, msg map[string]interface{}) (err error) {
for k, v := range msg {
switch t := v.(type) {
case map[string]interface{}:
writeKeyMap(w, k, t)
case []string:
writeKeyList(w, k, t)
case string:
writeKeyString(w, k, t)
case []interface{}:
str := make([]string, len(t))
for i := range t {
str[i] = t[i].(string)
}
writeKeyList(w, k, str)
default:
return fmt.Errorf("[writeMap] can not write type %T right now", msg)
}
}
return nil
}
//SECTION_START has been read already.
func readKeyMap(r *bufio.Reader) (key string, msg map[string]interface{}, err error) {
key, err = readString1(r)
if err != nil {
return
}
msg, err = readMap(r, false)
return
}
//LIST_START has been read already.
func readKeyList(r *bufio.Reader) (key string, msg []string, err error) {
key, err = readString1(r)
if err != nil {
return
}
msg = []string{}
for {
var c byte
c, err = r.ReadByte()
if err != nil {
return
}
switch elementType(c) {
case etLIST_ITEM:
value, err := readString2(r)
if err != nil {
return "", nil, err
}
msg = append(msg, value)
case etLIST_END: //end of outer list
return key, msg, nil
default:
return "", nil, fmt.Errorf("[readKeyList] protocol error 2")
}
}
return
}
//KEY_VALUE has been read already.
func readKeyString(r *bufio.Reader) (key string, msg string, err error) {
key, err = readString1(r)
if err != nil {
return
}
msg, err = readString2(r)
if err != nil {
return
}
return
}
// Since the original key chosen can have duplicates,
// this function is used to map the original key to a new one
// to make them unique.
func getNewKeyToHandleDuplicates(key string, msg map[string]interface{}) string {
if _, ok := msg[key]; !ok {
return key
}
for i := 0; ; i++ {
newKey := key + "##" + strconv.Itoa(i)
if _, ok := msg[newKey]; !ok {
return newKey
}
}
}
//SECTION_START has been read already.
func readMap(r *bufio.Reader, isRoot bool) (msg map[string]interface{}, err error) {
msg = map[string]interface{}{}
for {
c, err := r.ReadByte()
if err == io.EOF && isRoot { //may be root section
return msg, nil
}
if err != nil {
return nil, err
}
switch elementType(c) {
case etSECTION_START:
key, value, err := readKeyMap(r)
if err != nil {
return nil, err
}
msg[getNewKeyToHandleDuplicates(key, msg)] = value
case etLIST_START:
key, value, err := readKeyList(r)
if err != nil {
return nil, err
}
msg[getNewKeyToHandleDuplicates(key, msg)] = value
case etKEY_VALUE:
key, value, err := readKeyString(r)
if err != nil {
return nil, err
}
msg[getNewKeyToHandleDuplicates(key, msg)] = value
case etSECTION_END: //end of outer section
return msg, nil
default:
panic(fmt.Errorf("[readMap] protocol error 1, %d %#v", c, msg))
//return nil, fmt.Errorf("[readMap] protocol error 1, %d",c)
}
}
return
}