|
@@ -0,0 +1,359 @@
|
|
|
+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
|
|
|
+}
|