mirror of https://github.com/k3s-io/k3s
360 lines
7.3 KiB
Go
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
|
|
}
|