-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathutils.go
174 lines (150 loc) · 3.91 KB
/
utils.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
163
164
165
166
167
168
169
170
171
172
173
174
package p2pnet
import (
crand "crypto/rand"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"io"
"net"
"os"
"path/filepath"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
ma "github.com/multiformats/go-multiaddr"
)
// Message must be implemented by all network messages
type Message interface {
String() string
Encode() ([]byte, error)
Type() byte
}
// WriteStreamMessage writes the given message to the writer.
// The peer ID is only used for logging, as it's assumed the writer implementation
// is a stream opened with the given peer.
func WriteStreamMessage(s io.Writer, msg Message, peerID peer.ID) error {
encMsg, err := msg.Encode()
if err != nil {
return err
}
err = WriteStreamBytes(s, encMsg)
if err != nil {
return err
}
log.Debugf("Sent message to peer=%s type=%d", peerID, msg.Type())
return nil
}
// WriteStreamBytes writes the given bytes to the stream.
func WriteStreamBytes(s io.Writer, msg []byte) error {
err := binary.Write(s, binary.LittleEndian, uint32(len(msg)))
if err != nil {
return err
}
_, err = s.Write(msg)
if err != nil {
return err
}
return nil
}
// ReadStreamMessage reads the 4-byte LE size header and message body returning the
// message body bytes. io.EOF is returned if the stream is closed before any bytes
// are received. If a partial message is received before the stream closes,
// io.ErrUnexpectedEOF is returned.
func ReadStreamMessage(s io.Reader, maxMessageSize uint32) ([]byte, error) {
if s == nil {
return nil, errNilStream
}
lenBuf := make([]byte, 4) // uint32 size
n, err := io.ReadFull(s, lenBuf)
if err != nil {
if isEOF(err) {
if n > 0 {
err = io.ErrUnexpectedEOF
} else {
err = io.EOF
}
}
return nil, err
}
msgLen := binary.LittleEndian.Uint32(lenBuf)
if msgLen > maxMessageSize {
log.Warnf("received message longer than max allowed size: msg size=%d, max=%d",
msgLen, maxMessageSize)
return nil, fmt.Errorf("message size %d too large", msgLen)
}
msgBuf := make([]byte, msgLen)
_, err = io.ReadFull(s, msgBuf)
if err != nil {
if isEOF(err) {
err = io.ErrUnexpectedEOF
}
return nil, err
}
return msgBuf, nil
}
func isEOF(err error) bool {
switch {
case
errors.Is(err, net.ErrClosed), // what libp2p with QUIC usually generates
errors.Is(err, io.EOF),
errors.Is(err, io.ErrUnexpectedEOF),
errors.Is(err, io.ErrClosedPipe):
return true
default:
return false
}
}
// stringsToAddrInfos converts a string of peers in multiaddress format to a
// minimal set of multiaddr addresses.
func stringsToAddrInfos(peers []string) ([]peer.AddrInfo, error) {
madders := make([]ma.Multiaddr, len(peers))
for i, p := range peers {
ma, err := ma.NewMultiaddr(p)
if err != nil {
return nil, err
}
madders[i] = ma
}
return peer.AddrInfosFromP2pAddrs(madders...)
}
// generateKey generates an ed25519 private key and writes it to the past
// filepath.
func generateKey(fp string) (crypto.PrivKey, error) {
key, _, err := crypto.GenerateEd25519Key(crand.Reader)
if err != nil {
return nil, err
}
if err = saveKey(key, fp); err != nil {
return nil, err
}
return key, nil
}
// loadKey attempts to load a private key from the provided filepath
func loadKey(fp string) (crypto.PrivKey, error) {
keyData, err := os.ReadFile(filepath.Clean(fp))
if err != nil {
return nil, err
}
dec := make([]byte, hex.DecodedLen(len(keyData)))
_, err = hex.Decode(dec, keyData)
if err != nil {
return nil, err
}
return crypto.UnmarshalEd25519PrivateKey(dec)
}
// saveKey attempts to save a private key to the provided filepath
func saveKey(priv crypto.PrivKey, fp string) (err error) {
f, err := os.OpenFile(filepath.Clean(fp), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
return err
}
raw, err := priv.Raw()
if err != nil {
return err
}
hexBytes := []byte(hex.EncodeToString(raw))
if _, err = f.Write(hexBytes); err != nil {
return err
}
return f.Close()
}