glider/proxy/ss/cipher/shadowaead/conn.go

68 lines
1.2 KiB
Go

package shadowaead
import (
"crypto/rand"
"io"
"net"
)
type streamConn struct {
net.Conn
Cipher
r *reader
w *writer
}
// NewConn wraps a stream-oriented net.Conn with cipher.
func NewConn(c net.Conn, ciph Cipher) net.Conn { return &streamConn{Conn: c, Cipher: ciph} }
func (c *streamConn) initReader() error {
salt := make([]byte, c.SaltSize())
if _, err := io.ReadFull(c.Conn, salt); err != nil {
return err
}
aead, err := c.Decrypter(salt)
if err != nil {
return err
}
c.r = newReader(c.Conn, aead)
return nil
}
func (c *streamConn) Read(b []byte) (int, error) {
if c.r == nil {
if err := c.initReader(); err != nil {
return 0, err
}
}
return c.r.Read(b)
}
func (c *streamConn) initWriter() error {
salt := make([]byte, c.SaltSize())
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
return err
}
aead, err := c.Encrypter(salt)
if err != nil {
return err
}
_, err = c.Conn.Write(salt)
if err != nil {
return err
}
c.w = newWriter(c.Conn, aead)
return nil
}
func (c *streamConn) Write(b []byte) (int, error) {
if c.w == nil {
if err := c.initWriter(); err != nil {
return 0, err
}
}
return c.w.Write(b)
}