Skip to content

Commit

Permalink
Parse Events
Browse files Browse the repository at this point in the history
  • Loading branch information
dnfd committed May 11, 2020
1 parent f309330 commit 5ab5605
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 38 deletions.
37 changes: 25 additions & 12 deletions pkg/msg/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package msg

import (
"encoding/json"
"errors"
)

const (
Expand All @@ -11,8 +12,11 @@ const (
// Response type code
Response = 2

// Event type code
Event = 3
// EventPublic is public event type code
EventPublic = 3

// EventPrivate is private event type code
EventPrivate = 4
)

// Msg represent websocket messages, it could be either a request, a response or an event
Expand All @@ -34,17 +38,26 @@ func NewResponse(req *Msg, method string, args []interface{}) *Msg {
}

// Encode msg into json
func (m *Msg) Encode() []byte {
s, err := json.Marshal([]interface{}{
m.Type,
m.ReqID,
m.Method,
m.Args,
})
if err != nil {
return []byte{}
func (m *Msg) Encode() ([]byte, error) {
switch m.Type {
case Response, Request:
return json.Marshal([]interface{}{
m.Type,
m.ReqID,
m.Method,
m.Args,
})

case EventPrivate, EventPublic:
return json.Marshal([]interface{}{
m.Type,
m.Method,
m.Args,
})

default:
return nil, errors.New("invalid type")
}
return s
}

// Convss2is converts a string slice to interface slice more details: https://golang.org/doc/faq#convert_slice_of_interface)
Expand Down
5 changes: 4 additions & 1 deletion pkg/msg/msg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ func TestEncoding(t *testing.T) {
Args: []interface{}{"hello", "there"},
}

assert.Equal(t, `[1,42,"test",["hello","there"]]`, string(msg.Encode()))
enc, err := msg.Encode()

assert.NoError(t, err)
assert.Equal(t, `[1,42,"test",["hello","there"]]`, string(enc))
}
58 changes: 41 additions & 17 deletions pkg/msg/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,37 +73,61 @@ func ParseSliceOfStrings(t interface{}) ([]string, error) {

func Parse(msg []byte) (*Msg, error) {
req := Msg{}

var v []interface{}
if err := json.Unmarshal(msg, &v); err != nil {
return nil, fmt.Errorf("Could not parse message: %w", err)
}

if len(v) != 4 {
return nil, errors.New("message must contains 4 elements")
if len(v) < 3 {
return nil, errors.New("message is too small")
}

t, err := ParseUint8(v[0])
if err != nil {
return nil, fmt.Errorf("failed to parse type: %w", err)
}
if t != Request && t != Response && t != Event {
return nil, errors.New("message type must be 1, 2 or 3")
}

reqID, err := ParseUint64(v[1])
if err != nil {
return nil, fmt.Errorf("failed to parse request ID: %w", err)
}
var reqID uint64
var method string
var args []interface{}

method, err := ParseString(v[2])
if err != nil {
return nil, fmt.Errorf("failed to parse method: %w", err)
}
switch t {
case Request, Response:
if len(v) != 4 {
return nil, errors.New("message must contain 4 elements")
}

args, err := ParseSlice(v[3])
if err != nil {
return nil, fmt.Errorf("failed to parse arguments: %w", err)
reqID, err = ParseUint64(v[1])
if err != nil {
return nil, fmt.Errorf("failed to parse request ID: %w", err)
}

method, err = ParseString(v[2])
if err != nil {
return nil, fmt.Errorf("failed to parse method: %w", err)
}

args, err = ParseSlice(v[3])
if err != nil {
return nil, fmt.Errorf("failed to parse arguments: %w", err)
}

case EventPrivate, EventPublic:
if len(v) != 3 {
return nil, errors.New("message must contain 3 elements")
}

method, err = ParseString(v[1])
if err != nil {
return nil, fmt.Errorf("failed to parse method: %w", err)
}

args, err = ParseSlice(v[2])
if err != nil {
return nil, fmt.Errorf("failed to parse arguments: %w", err)
}
default:
return nil, errors.New("message type must be 1, 2, 3 or 4")
}

req.Type = t
Expand Down
16 changes: 10 additions & 6 deletions pkg/msg/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ func TestParserSuccess(t *testing.T) {
Args: []interface{}{},
}, msg)

msg, err = Parse([]byte(`[3,42,"temperature",[28.7]]`))
msg, err = Parse([]byte(`[3,"temperature",[28.7]]`))
assert.NoError(t, err)
assert.Equal(t,
&Msg{
Type: Event,
ReqID: 42,
Type: EventPublic,
ReqID: 0,
Method: "temperature",
Args: []interface{}{28.7},
}, msg)
}

func TestParserErrorsMessageLength(t *testing.T) {
msg, err := Parse([]byte(`[1,42,"ping"]`))
assert.EqualError(t, err, "message must contains 4 elements")
assert.EqualError(t, err, "message must contain 4 elements")
assert.Nil(t, msg)
}

Expand All @@ -51,8 +51,12 @@ func TestParserErrorsBadJSON(t *testing.T) {
}

func TestParserErrorsType(t *testing.T) {
msg, err := Parse([]byte(`[4,42,"ping",[]]`))
assert.EqualError(t, err, "message type must be 1, 2 or 3")
msg, err := Parse([]byte(`[5,42,"ping",[]]`))
assert.EqualError(t, err, "message type must be 1, 2, 3 or 4")
assert.Nil(t, msg)

msg, err = Parse([]byte(`[5,"ping",[]]`))
assert.EqualError(t, err, "message type must be 1, 2, 3 or 4")
assert.Nil(t, msg)

msg, err = Parse([]byte(`[1.1,42,"pong",[]]`))
Expand Down
7 changes: 6 additions & 1 deletion pkg/routing/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,12 @@ func (c *Client) read() {
req, err := msg.Parse(message)
if err != nil {
log.Error().Msgf("fail to parse message: %s", err.Error())
c.send <- msg.NewResponse(&msg.Msg{ReqID: 0}, "error", []interface{}{err.Error()}).Encode()

resp, err := msg.NewResponse(&msg.Msg{ReqID: 0}, "error", []interface{}{err.Error()}).Encode()
if err == nil {
c.send <- resp
}

continue
}

Expand Down
5 changes: 4 additions & 1 deletion pkg/routing/hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ func (h *Hub) ListenWebsocketEvents() {
select {
case req := <-h.Requests:
resp := h.handleRequest(&req)
req.client.Send(string(resp.Encode()))
encoded, err := resp.Encode()
if err == nil {
req.client.Send(string(encoded))
}

case client := <-h.Unregister:
log.Info().Msgf("Unregistering client %s", client.GetUID())
Expand Down

0 comments on commit 5ab5605

Please sign in to comment.