-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
command.go
162 lines (143 loc) · 3.6 KB
/
command.go
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright 2021-22 Kirill Scherba <[email protected]>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Teonet command module
package teonet
import (
"errors"
)
// Error command packet too short
var ErrCommandTooShort = errors.New("command packet too short")
// Command struct and method receiver
type Command struct {
Cmd byte
Data []byte
teo *Teonet
}
// Command create command struct. Attr may contain 1 or 2 parameters:
//
// 1 parameter
// command & data slice - []byte
//
// 2 parameters
// command - AuthCmd | byte | int
// data - []byte | string | nil
func (teo *Teonet) Command(attr ...interface{}) (cmd *Command) {
cmd = &Command{teo: teo}
switch len(attr) {
case 1:
switch c := attr[0].(type) {
case []byte:
cmd.UnmarshalBinary(c)
default:
panic("wrong data attribute")
}
case 2:
// command
switch c := attr[0].(type) {
case AuthCmd:
cmd.Cmd = byte(c)
case byte:
cmd.Cmd = c
case int:
cmd.Cmd = byte(c)
default:
panic("wrong cmd attribute")
}
// data
switch d := attr[1].(type) {
case []byte:
cmd.Data = d
case string:
cmd.Data = []byte(d)
case nil:
// empty data
default:
panic("wrong data attribute")
}
}
return
}
// Bytes binary marshal command struct and return byte slice
func (c Command) Bytes() (data []byte) {
data, _ = c.MarshalBinary()
return
}
// Send command to channel
func (c Command) Send(channel *Channel, attr ...interface{}) (id int, err error) {
// Add teo to attr, it need for subscribe to answer
if len(attr) > 0 {
attr = append([]interface{}{c.teo}, attr...)
}
return channel.Send(c.Bytes(), attr...)
}
// SendTo send command to channel by address
func (c Command) SendTo(addr string, attr ...interface{}) (id int, err error) {
// Add teo to attr, it need for subscribe to answer
if len(attr) > 0 {
attr = append([]interface{}{c.teo}, attr...)
}
return c.teo.SendTo(addr, c.Bytes(), attr...)
}
// MarshalBinary binary marshal command struct
func (c Command) MarshalBinary() (data []byte, err error) {
data = append([]byte{c.Cmd}, c.Data...)
return
}
// UnmarshalBinary binary unmarshal command struct
func (c *Command) UnmarshalBinary(data []byte) (err error) {
if len(data) < 1 {
return ErrCommandTooShort
}
c.Cmd = data[0]
c.Data = data[1:]
return
}
// TeonetCommand is teonet command interface methods receiver
type TeonetCommand struct {
*Teonet
}
// NewCommandInterface create teonet client with command interfeice connected
func NewCommandInterface(appName string, attr ...interface{}) (teo *TeonetCommand, err error) {
t, err := New(appName, attr...)
if err != nil {
return
}
teo = commandInterface(t)
return
}
// commandInterface make new teonet command interface
func commandInterface(t *Teonet) (teo *TeonetCommand) {
teo = &TeonetCommand{t}
return
}
// SendAnswer send command answer
func (teo TeonetCommand) SendAnswer(i interface{}, cmd byte, data []byte) (n int, err error) {
pac := i.(*Packet)
return teo.SendTo(pac.From(), cmd, data)
}
// SendTo send to address
func (teo TeonetCommand) SendTo(addr string, cmd byte, data []byte) (n int, err error) {
id, err := teo.Command(cmd, data).SendTo(addr)
n = int(id)
return
}
// WaitFrom wait answer from address
func (teo TeonetCommand) WaitFrom(addr string, cmd byte, attr ...interface{}) <-chan *struct {
Data []byte
Err error
} {
ch := make(chan *struct {
Data []byte
Err error
})
attr = append(attr, cmd)
go func() {
data, err := teo.Teonet.WaitFrom(addr, attr...)
ch <- &struct {
Data []byte
Err error
}{data, err}
}()
return ch
}