/
messages.go
140 lines (114 loc) · 2.75 KB
/
messages.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
package jsonapi
import (
"bufio"
"bytes"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"io"
)
type messageType struct {
Type string `json:"type"`
}
type queryMessage struct {
Query string `json:"query"`
}
type queryHostMessage struct {
Host string `json:"host"`
}
type getLoginMessage struct {
Entry string `json:"entry"`
}
type copyToClipboard struct {
Entry string `json:"entry"`
Key string `json:"key"`
}
type loginResponse struct {
Username string `json:"username"`
Password string `json:"password"`
LoginFields map[string]interface{} `json:"login_fields,omitempty"`
}
type getDataMessage struct {
Entry string `json:"entry"`
}
type getVersionMessage struct {
Version string `json:"version"`
Major uint64 `json:"major"`
Minor uint64 `json:"minor"`
Patch uint64 `json:"patch"`
}
type createEntryMessage struct {
Name string `json:"entry_name"`
Login string `json:"login"`
Password string `json:"password"`
PasswordLength int `json:"length"`
Generate bool `json:"generate"`
UseSymbols bool `json:"use_symbols"`
}
type statusResponse struct {
Status string `json:"status"`
}
type errorResponse struct {
Error string `json:"error"`
}
func readRequest(r io.Reader) ([]byte, error) {
input := bufio.NewReader(r)
lenBytes := make([]byte, 4)
count, err := input.Read(lenBytes)
if err != nil {
return nil, eofReturn(err)
}
if count != 4 {
return nil, fmt.Errorf("not enough bytes read to determine message size")
}
length, err := getMessageLength(lenBytes)
if err != nil {
return nil, err
}
msgBytes := make([]byte, length)
count, err = input.Read(msgBytes)
if err != nil {
return nil, eofReturn(err)
}
if count != length {
return nil, fmt.Errorf("incomplete message read")
}
return msgBytes, nil
}
func getMessageLength(msg []byte) (int, error) {
var length uint32
buf := bytes.NewBuffer(msg)
if err := binary.Read(buf, binary.LittleEndian, &length); err != nil {
return 0, err
}
return int(length), nil
}
func eofReturn(err error) error {
if errors.Is(err, io.EOF) {
return nil
}
return err
}
func sendResponse(msg any, w io.Writer) error {
// we can't use json.NewEncoder(w).Encode because we need to send the final
// message length before the actual JSON
buf, err := json.Marshal(msg)
if err != nil {
return err
}
if err := writeMessageLength(buf, w); err != nil {
return err
}
n, err := w.Write(buf)
if err != nil {
return fmt.Errorf("failed to write message: %w", err)
}
if n != len(buf) {
return fmt.Errorf("message not fully written (wrote %d of %d)", n, len(buf))
}
return nil
}
func writeMessageLength(msg []byte, w io.Writer) error {
return binary.Write(w, binary.LittleEndian, uint32(len(msg)))
}