summaryrefslogtreecommitdiff
path: root/protocol/client_recv.go
blob: eb406c29f7d728bae84a82bb71de3e26dfab1882 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package protocol

import (
	"bytes"
	"fmt"
	"io"
)

func (c *Client) Receive() (Message, error) {
	var cmd [3]byte
	_, err := io.ReadFull(c.rx, cmd[:])
	if err != nil {
		return nil, err
	}
	typ := Command(cmd[:])
	switch typ {
	case CmdMsg:
		var length uint64
		err = c.read(&length)
		if err != nil {
			return nil, err
		}
		data := make([]byte, length)
		_, err = io.ReadFull(c.rx, data)
		if err != nil {
			return nil, err
		}
		return commandMsg{
			data: data,
		}, nil
	case CmdNop:
		fallthrough
	case CmdBye:
		fallthrough
	case CmdNil:
		return trivialCommand(typ), nil
	default:
		return nil, fmt.Errorf("unknown command from server: %v", string(cmd[:]))
	}
}

type Message interface {
	Command() Command
	// Consume calls messageConsumer is this message contains a data message to the upper level.
	Consume(messageConsumer func(reader io.Reader, length int64))
}

type trivialCommand Command

func (t trivialCommand) Consume(func(reader io.Reader, length int64)) {}

func (t trivialCommand) Command() Command {
	return Command(t)
}

type commandMsg struct {
	data []byte
}

func (c commandMsg) Consume(messageConsumer func(reader io.Reader, length int64)) {
	messageConsumer(bytes.NewReader(c.data), int64(len(c.data)))
}

func (c commandMsg) Command() Command {
	return CmdMsg
}