replace outermost framing on tcp connection
switch from gob to length-prefix encoding
This commit is contained in:
1 parent
af049efb40
commit
6f8622a1a0
2 files changed
+47
-9
No files matched your search
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/andybalholm/go-bit"
|
||||
@@ -336,6 +337,10 @@ type GobTCPSender struct {
|
||||
encoder *gob.Encoder
|
||||
}
|
||||
|
||||
type LengthPrefixTCPSender struct {
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
type EncryptedTCPSender struct {
|
||||
sync.RWMutex
|
||||
sender TCPSender
|
||||
@@ -350,6 +355,21 @@ func (sender *GobTCPSender) Send(msg []byte) error {
|
||||
return sender.encoder.Encode(msg)
|
||||
}
|
||||
|
||||
func NewLengthPrefixTCPSender(writer io.Writer) *LengthPrefixTCPSender {
|
||||
return &LengthPrefixTCPSender{writer: writer}
|
||||
}
|
||||
|
||||
func (sender *LengthPrefixTCPSender) Send(msg []byte) error {
|
||||
l := len(msg)
|
||||
// We copy the message so we can send it in a single Write
|
||||
// operation, thus making this thread-safe without locking.
|
||||
prefixedMsg := make([]byte, 4+l)
|
||||
binary.BigEndian.PutUint32(prefixedMsg, uint32(l))
|
||||
copy(prefixedMsg[4:], msg)
|
||||
_, err := sender.writer.Write(prefixedMsg)
|
||||
return err
|
||||
}
|
||||
|
||||
func NewEncryptedTCPSender(sender TCPSender, sessionKey *[32]byte, outbound bool) *EncryptedTCPSender {
|
||||
return &EncryptedTCPSender{sender: sender, state: NewTCPCryptoState(sessionKey, outbound)}
|
||||
}
|
||||
@@ -370,6 +390,10 @@ type GobTCPReceiver struct {
|
||||
decoder *gob.Decoder
|
||||
}
|
||||
|
||||
type LengthPrefixTCPReceiver struct {
|
||||
reader io.Reader
|
||||
}
|
||||
|
||||
type EncryptedTCPReceiver struct {
|
||||
receiver TCPReceiver
|
||||
state *TCPCryptoState
|
||||
@@ -385,6 +409,21 @@ func (receiver *GobTCPReceiver) Receive() ([]byte, error) {
|
||||
return msg, err
|
||||
}
|
||||
|
||||
func NewLengthPrefixTCPReceiver(reader io.Reader) *LengthPrefixTCPReceiver {
|
||||
return &LengthPrefixTCPReceiver{reader: reader}
|
||||
}
|
||||
|
||||
func (receiver *LengthPrefixTCPReceiver) Receive() ([]byte, error) {
|
||||
lenPrefix := make([]byte, 4)
|
||||
if _, err := io.ReadFull(receiver.reader, lenPrefix); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := binary.BigEndian.Uint32(lenPrefix)
|
||||
msg := make([]byte, l)
|
||||
_, err := io.ReadFull(receiver.reader, msg)
|
||||
return msg, err
|
||||
}
|
||||
|
||||
func NewEncryptedTCPReceiver(receiver TCPReceiver, sessionKey *[32]byte, outbound bool) *EncryptedTCPReceiver {
|
||||
return &EncryptedTCPReceiver{receiver: receiver, state: NewTCPCryptoState(sessionKey, !outbound)}
|
||||
}
|
||||
|
||||
+8
-9
@@ -228,12 +228,11 @@ func filterV1Features(intro map[string]string) map[string]string {
|
||||
// - When the connection is encrypted, 32 bytes follow containing the
|
||||
// public key.
|
||||
//
|
||||
// - Then a stream of gobified values.
|
||||
// - Then a stream of length-prefixed messages, which are encrypted
|
||||
// for an encrypted connection.
|
||||
//
|
||||
// The gobified values are the messages on the connection (encrypted
|
||||
// for an encrypted connection). The first message contains the
|
||||
// encoded features map (so in contrast to V1, it will be encrypted on
|
||||
// an encrypted connection).
|
||||
// The first message contains the encoded features map (so in contrast
|
||||
// to V1, it will be encrypted on an encrypted connection).
|
||||
func (res *ProtocolIntroResults) doIntroV2(params ProtocolIntroParams, pubKey, privKey *[32]byte) error {
|
||||
// Public key exchange
|
||||
var wbuf []byte
|
||||
@@ -266,8 +265,8 @@ func (res *ProtocolIntroResults) doIntroV2(params ProtocolIntroParams, pubKey, p
|
||||
return ErrExpectedCrypto
|
||||
}
|
||||
|
||||
res.Sender = NewGobTCPSender(gob.NewEncoder(params.Conn))
|
||||
res.Receiver = NewGobTCPReceiver(gob.NewDecoder(params.Conn))
|
||||
res.Sender = NewLengthPrefixTCPSender(params.Conn)
|
||||
res.Receiver = NewLengthPrefixTCPReceiver(params.Conn)
|
||||
|
||||
case 1:
|
||||
if pubKey == nil {
|
||||
@@ -279,8 +278,8 @@ func (res *ProtocolIntroResults) doIntroV2(params ProtocolIntroParams, pubKey, p
|
||||
return err
|
||||
}
|
||||
|
||||
res.Sender = NewGobTCPSender(gob.NewEncoder(params.Conn))
|
||||
res.Receiver = NewGobTCPReceiver(gob.NewDecoder(params.Conn))
|
||||
res.Sender = NewLengthPrefixTCPSender(params.Conn)
|
||||
res.Receiver = NewLengthPrefixTCPReceiver(params.Conn)
|
||||
res.setupCrypto(params, rbuf, privKey)
|
||||
|
||||
default:
|
||||
|
||||
Reference in new issue
Block a user