replace outermost framing on tcp connection

switch from gob to length-prefix encoding
This commit is contained in:
Matthias Radestock committed 2015-07-20 23:51:04 +01:00
1 parent af049efb40
commit 6f8622a1a0
2 files changed
+47 -9

No files matched your search

+39
View File
@@ -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
View File
@@ -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: