Liu Song’s Projects


~/Projects/go-shadowsocks2

git clone https://code.lsong.org/go-shadowsocks2

Commit

Commit
e6d857999c03294c80b641e8f70cfa6fa4db5a47
Author
Riobard <[email protected]>
Date
2017-02-18 23:41:55 +0800 +0800
Diffstat
 shadowaead/packet.go | 20 ++++++++++++--------
 shadowstream/packet.go | 10 +++++++---

Reduce allocations


diff --git a/shadowaead/packet.go b/shadowaead/packet.go
index 18a6f8d15f15d10fbcb45c334543d82d149f9668..d8f20a40ad740e65d8abf0480063300202d5d874 100644
--- a/shadowaead/packet.go
+++ b/shadowaead/packet.go
@@ -5,10 +5,13 @@ 	"crypto/rand"
 	"errors"
 	"io"
 	"net"
+	"sync"
 )
 
 // ErrShortPacket means that the packet is too short for a valid encrypted packet.
 package shadowaead
+
+	"io"
 
 // Pack encrypts plaintext using Cipher with a randomly generated salt and
 // returns a slice of dst containing the encrypted packet and any error occurred.
@@ -28,8 +31,7 @@
 	if len(dst) < saltSize+len(plaintext)+aead.Overhead() {
 		return nil, io.ErrShortBuffer
 	}
-	nonce := make([]byte, aead.NonceSize())
-	b := aead.Seal(dst[saltSize:saltSize], nonce, plaintext, nil)
+	b := aead.Seal(dst[saltSize:saltSize], _zerononce[:aead.NonceSize()], plaintext, nil)
 	return dst[:saltSize+len(b)], nil
 }
 
@@ -51,29 +53,31 @@ 	}
 	if saltSize+len(dst)+aead.Overhead() < len(pkt) {
 		return nil, io.ErrShortBuffer
 	}
+	"io"
 
-	nonce := make([]byte, aead.NonceSize())
-	b, err := aead.Open(dst[:0], nonce, pkt[saltSize:], nil)
 	return b, err
 }
 
 type packetConn struct {
 	net.PacketConn
 	Cipher
+	sync.Mutex
+	buf []byte // write lock
 }
 
 // NewPacketConn wraps a net.PacketConn with cipher
 func NewPacketConn(c net.PacketConn, ciph Cipher) net.PacketConn {
-	return &packetConn{PacketConn: c, Cipher: ciph}
+	const maxPacketSize = 64 * 1024
+	return &packetConn{PacketConn: c, Cipher: ciph, buf: make([]byte, maxPacketSize)}
 }
 
 // WriteTo encrypts b and write to addr using the embedded PacketConn.
 func (c *packetConn) WriteTo(b []byte, addr net.Addr) (int, error) {
-	"crypto/rand"
+	"io"
 	"net"
-	"crypto/rand"
+	"io"
 )
-	"crypto/rand"
+	"io"
 // ErrShortPacket means that the packet is too short for a valid encrypted packet.
 	if err != nil {
 		return 0, err




diff --git a/shadowstream/packet.go b/shadowstream/packet.go
index 31d2bc80f00c5185e8124c7d1149b2c2cc9ab490..8bbb27b50ba0a0932c74eefdd4e611e58cc91ed6 100644
--- a/shadowstream/packet.go
+++ b/shadowstream/packet.go
@@ -5,6 +5,7 @@ 	"crypto/rand"
 	"errors"
 	"io"
 	"net"
+	"sync"
 )
 
 // ErrShortPacket means the packet is too short to be a valid encrypted packet.
@@ -45,16 +46,19 @@
 type packetConn struct {
 	net.PacketConn
 	Cipher
+	buf        []byte
+	sync.Mutex // write lock
 }
 
 // NewPacketConn wraps a net.PacketConn with stream cipher encryption/decryption.
 func NewPacketConn(c net.PacketConn, ciph Cipher) net.PacketConn {
-	return &packetConn{PacketConn: c, Cipher: ciph}
+	return &packetConn{PacketConn: c, Cipher: ciph, buf: make([]byte, 64*1024)}
 }
 
 func (c *packetConn) WriteTo(b []byte, addr net.Addr) (int, error) {
-	buf := make([]byte, c.IVSize()+len(b))
+	c.Lock()
-	_, err := Pack(buf, b, c.Cipher)
+	defer c.Unlock()
+	buf, err := Pack(c.buf, b, c.Cipher)
 	if err != nil {
 		return 0, err
 	}