From 6a517673246dceb612ecbb5b0b602da37038b072 Mon Sep 17 00:00:00 2001 From: wener Date: Thu, 6 May 2021 23:43:42 +0800 Subject: [PATCH] support simple multi line #5 --- ami/conn_internal.go | 2 +- ami/connect.go | 2 +- ami/msg.go | 37 ++++++++++++++++++++++++++++----- ami/msg_test.go | 49 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 76 insertions(+), 14 deletions(-) diff --git a/ami/conn_internal.go b/ami/conn_internal.go index db88178..e34ec2c 100644 --- a/ami/conn_internal.go +++ b/ami/conn_internal.go @@ -87,7 +87,7 @@ func (c *Conn) loop(ctx context.Context) (err error) { // send pending message msg := async.msg - log.Sugar().With("id", async.id, "type", msg.Type, "name", msg.Name).Debug("send message") + //log.Sugar().With("id", async.id, "type", msg.Type, "name", msg.Name).Debug("send message") err = msg.Write(c.conn) diff --git a/ami/connect.go b/ami/connect.go index a6cf8bd..e4c12b0 100644 --- a/ami/connect.go +++ b/ami/connect.go @@ -230,7 +230,7 @@ func (c *Conn) connect(conn net.Conn) (err error) { } log.Info("login success") } - log.Sugar().Debug("do conn check ping") + //log.Sugar().Debug("do conn check ping") // be ready _, err = c.Request(amimodels.PingAction{}) return diff --git a/ami/msg.go b/ami/msg.go index 68caf99..a4fd6ce 100644 --- a/ami/msg.go +++ b/ami/msg.go @@ -47,22 +47,49 @@ func (m *Message) Read(r *bufio.Reader) (err error) { return errors.Errorf("invalid message type: %q", sp[0]) } + var stack [][]string for { + // may contain BOM line, err = r.ReadString('\n') if err != nil { return err } - line = strings.TrimSuffix(line, "\r\n") - if len(line) == 0 { + if line == "\r\n" { break } sp = strings.SplitN(line, ":", 2) - if len(sp) != 2 { - return errors.Errorf("invalid attr line read(%v: %v): %q", m.Type, m.Name, line) + + switch { + case len(sp) == 2 && strings.HasSuffix(line, "\r\n"): + // valid line + stack = append(stack, sp) + case len(stack) == 0 && len(sp) == 2: + // first line + stack = append(stack, sp) + case len(stack) != 0: + // continue line + stack = append(stack, []string{"", line}) } - m.Attributes[sp[0]] = strings.TrimSpace(sp[1]) } + var k, v string + for _, pair := range stack { + switch { + case pair[0] != "" && k != "": + m.Attributes[k] = strings.TrimSuffix(v, "\r\n") + k = "" + v = "" + fallthrough + case pair[0] != "": + k = pair[0] + v = strings.TrimLeft(pair[1], " ") + case pair[0] == "": + v += pair[1] + } + } + if k != "" { + m.Attributes[k] = strings.TrimSuffix(v, "\r\n") + } return } func (m *Message) Write(w io.Writer) (err error) { diff --git a/ami/msg_test.go b/ami/msg_test.go index dcacc78..468c491 100644 --- a/ami/msg_test.go +++ b/ami/msg_test.go @@ -6,6 +6,8 @@ import ( "github.com/stretchr/testify/assert" amimodels "github.com/wenerme/astgo/ami/models" "io" + "sort" + "strings" "testing" ) @@ -14,21 +16,54 @@ func TestMsgIO(t *testing.T) { msg *Message out string }{ - {msg: &Message{ - Type: MessageTypeEvent, - Name: "FullyBooted", - Attributes: map[string]interface{}{ - "Uptime": "1234", + { + msg: &Message{ + Type: MessageTypeEvent, + Name: "Name", + Attributes: map[string]interface{}{ + "Text": "12\r\n34", + "More": "Yes", + }, }, + // more after multi line + out: "Event: Name\r\nText: 12\r\n34\r\nMore: Yes\r\n\r\n", + }, + { + msg: &Message{ + Type: MessageTypeEvent, + Name: "Name", + Attributes: map[string]interface{}{ + "Text": "12\r\n34", + }, + }, + // simple multi line + out: "Event: Name\r\nText: 12\r\n34\r\n\r\n", + }, + + { + msg: &Message{ + Type: MessageTypeEvent, + Name: "FullyBooted", + Attributes: map[string]interface{}{ + "Uptime": "1234", + }, + }, + out: "Event: FullyBooted\r\nUptime: 1234\r\n\r\n", }, - out: "Event: FullyBooted\r\nUptime: 1234\r\n\r\n"}, {msg: MustConvertToMessage(amimodels.FullyBootedEvent{ Uptime: "1234", }), out: "Event: FullyBooted\r\nUptime: 1234\r\n\r\n"}, } { msg := test.msg - assert.Equal(t, test.out, msg.Format()) + + // ignore order + exp := strings.Split(test.out, "\r\n") + act := strings.Split(msg.Format(), "\r\n") + sort.Strings(exp) + sort.Strings(act) + assert.Equal(t, exp, act) + r := bufio.NewReader(bytes.NewReader([]byte(test.out))) rm := &Message{} assert.NoError(t, rm.Read(r))