mirror of
https://github.com/SagerNet/sing-shadowsocks.git
synced 2025-04-05 21:07:44 +03:00
Add vectorised interface
This commit is contained in:
parent
7e47fd1a99
commit
484a11603b
6 changed files with 105 additions and 37 deletions
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module github.com/sagernet/sing-shadowsocks
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/sagernet/sing v0.0.0-20220811135544-169983a8d773
|
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
|
||||||
lukechampine.com/blake3 v1.1.7
|
lukechampine.com/blake3 v1.1.7
|
||||||
)
|
)
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,8 +1,8 @@
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
|
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||||
github.com/sagernet/sing v0.0.0-20220811135544-169983a8d773 h1:n88c8oBC6GWbEW2+F4HkVAji+puSW3GYGrbnXmuVYsw=
|
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f h1:ekLjKIYjtkZNRN1c1IoNcpAsVZNKtO+Qe5cuHOwX0EI=
|
||||||
github.com/sagernet/sing v0.0.0-20220811135544-169983a8d773/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
|
||||||
|
|
|
@ -353,6 +353,40 @@ func (w *Writer) Write(p []byte) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Writer) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
|
defer buf.ReleaseMulti(buffers)
|
||||||
|
var index int
|
||||||
|
var err error
|
||||||
|
for _, buffer := range buffers {
|
||||||
|
pLen := buffer.Len()
|
||||||
|
if pLen > w.maxPacketSize {
|
||||||
|
_, err = w.Write(buffer.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if cap(w.buffer) < index+PacketLengthBufferSize+pLen+2*Overhead {
|
||||||
|
_, err = w.upstream.Write(w.buffer[:index])
|
||||||
|
index = 0
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binary.BigEndian.PutUint16(w.buffer[index:index+PacketLengthBufferSize], uint16(pLen))
|
||||||
|
w.cipher.Seal(w.buffer[index:index], w.nonce, w.buffer[index:index+PacketLengthBufferSize], nil)
|
||||||
|
increaseNonce(w.nonce)
|
||||||
|
offset := index + Overhead + PacketLengthBufferSize
|
||||||
|
w.cipher.Seal(w.buffer[offset:offset], w.nonce, buffer.Bytes(), nil)
|
||||||
|
increaseNonce(w.nonce)
|
||||||
|
index = offset + pLen + Overhead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index > 0 {
|
||||||
|
_, err = w.upstream.Write(w.buffer[:index])
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Writer) Buffer() *buf.Buffer {
|
func (w *Writer) Buffer() *buf.Buffer {
|
||||||
return buf.With(w.buffer)
|
return buf.With(w.buffer)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ const (
|
||||||
RequestHeaderFixedChunkLength = 1 + 8 + 2
|
RequestHeaderFixedChunkLength = 1 + 8 + 2
|
||||||
PacketMinimalHeaderSize = 30
|
PacketMinimalHeaderSize = 30
|
||||||
|
|
||||||
HeaderTypeClientEncrypted = 10
|
// HeaderTypeClientEncrypted = 10
|
||||||
HeaderTypeServerEncrypted = 11
|
// HeaderTypeServerEncrypted = 11
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -223,7 +223,7 @@ type clientConn struct {
|
||||||
destination M.Socksaddr
|
destination M.Socksaddr
|
||||||
requestSalt []byte
|
requestSalt []byte
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
writer io.Writer
|
writer *shadowaead.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Method) writeExtendedIdentityHeaders(request *buf.Buffer, salt []byte) error {
|
func (m *Method) writeExtendedIdentityHeaders(request *buf.Buffer, salt []byte) error {
|
||||||
|
@ -259,11 +259,11 @@ func (m *Method) writeExtendedIdentityHeaders(request *buf.Buffer, salt []byte)
|
||||||
|
|
||||||
func (c *clientConn) writeRequest(payload []byte) error {
|
func (c *clientConn) writeRequest(payload []byte) error {
|
||||||
var headerType byte
|
var headerType byte
|
||||||
if c.encryptedProtocolExtension && isTLSHandshake(payload) {
|
//if c.encryptedProtocolExtension && isTLSHandshake(payload) {
|
||||||
headerType = HeaderTypeClientEncrypted
|
// headerType = HeaderTypeClientEncrypted
|
||||||
} else {
|
//} else {
|
||||||
headerType = HeaderTypeClient
|
headerType = HeaderTypeClient
|
||||||
}
|
//}
|
||||||
|
|
||||||
salt := make([]byte, c.keySaltLength)
|
salt := make([]byte, c.keySaltLength)
|
||||||
common.Must1(io.ReadFull(rand.Reader, salt))
|
common.Must1(io.ReadFull(rand.Reader, salt))
|
||||||
|
@ -301,8 +301,8 @@ func (c *clientConn) writeRequest(payload []byte) error {
|
||||||
switch headerType {
|
switch headerType {
|
||||||
case HeaderTypeClient:
|
case HeaderTypeClient:
|
||||||
payloadLen = len(payload)
|
payloadLen = len(payload)
|
||||||
case HeaderTypeClientEncrypted:
|
// case HeaderTypeClientEncrypted:
|
||||||
payloadLen = readTLSChunkEnd(payload)
|
// payloadLen = readTLSChunkEnd(payload)
|
||||||
}
|
}
|
||||||
variableLengthHeaderLen += payloadLen
|
variableLengthHeaderLen += payloadLen
|
||||||
common.Must(binary.Write(fixedLengthBuffer, binary.BigEndian, uint16(variableLengthHeaderLen)))
|
common.Must(binary.Write(fixedLengthBuffer, binary.BigEndian, uint16(variableLengthHeaderLen)))
|
||||||
|
@ -331,7 +331,7 @@ func (c *clientConn) writeRequest(payload []byte) error {
|
||||||
c.requestSalt = salt
|
c.requestSalt = salt
|
||||||
if headerType == HeaderTypeClient {
|
if headerType == HeaderTypeClient {
|
||||||
c.writer = writer
|
c.writer = writer
|
||||||
} else if headerType == HeaderTypeClientEncrypted {
|
} /* else if headerType == HeaderTypeClientEncrypted {
|
||||||
encryptedWriter := NewTLSEncryptedStreamWriter(writer)
|
encryptedWriter := NewTLSEncryptedStreamWriter(writer)
|
||||||
if payloadLen < len(payload) {
|
if payloadLen < len(payload) {
|
||||||
_, err = encryptedWriter.Write(payload[payloadLen:])
|
_, err = encryptedWriter.Write(payload[payloadLen:])
|
||||||
|
@ -340,7 +340,7 @@ func (c *clientConn) writeRequest(payload []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.writer = encryptedWriter
|
c.writer = encryptedWriter
|
||||||
}
|
}*/
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ func (c *clientConn) readResponse() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if headerType != HeaderTypeServer && headerType != HeaderTypeServerEncrypted {
|
if headerType != HeaderTypeServer /* && headerType != HeaderTypeServerEncrypted*/ {
|
||||||
return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeServer, ", got ", headerType)
|
return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeServer, ", got ", headerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,9 +425,9 @@ func (c *clientConn) readResponse() error {
|
||||||
}
|
}
|
||||||
if headerType == HeaderTypeServer {
|
if headerType == HeaderTypeServer {
|
||||||
c.reader = reader
|
c.reader = reader
|
||||||
} else if headerType == HeaderTypeServerEncrypted {
|
} /*else if headerType == HeaderTypeServerEncrypted {
|
||||||
c.reader = NewTLSEncryptedStreamReader(reader)
|
c.reader = NewTLSEncryptedStreamReader(reader)
|
||||||
}
|
}*/
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,6 +456,21 @@ func (c *clientConn) Write(p []byte) (n int, err error) {
|
||||||
return c.writer.Write(p)
|
return c.writer.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ N.VectorisedWriter = (*clientConn)(nil)
|
||||||
|
|
||||||
|
func (c *clientConn) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
|
if c.writer != nil {
|
||||||
|
return c.writer.WriteVectorised(buffers)
|
||||||
|
}
|
||||||
|
err := c.writeRequest(buffers[0].Bytes())
|
||||||
|
if err != nil {
|
||||||
|
buf.ReleaseMulti(buffers)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buffers[0].Release()
|
||||||
|
return c.writer.WriteVectorised(buffers[1:])
|
||||||
|
}
|
||||||
|
|
||||||
func (c *clientConn) ReadFrom(r io.Reader) (n int64, err error) {
|
func (c *clientConn) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
if c.writer == nil {
|
if c.writer == nil {
|
||||||
return bufio.ReadFrom0(c, r)
|
return bufio.ReadFrom0(c, r)
|
||||||
|
|
|
@ -163,7 +163,7 @@ func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.M
|
||||||
return E.Cause(err, "read header")
|
return E.Cause(err, "read header")
|
||||||
}
|
}
|
||||||
|
|
||||||
if headerType != HeaderTypeClient && headerType != HeaderTypeClientEncrypted {
|
if headerType != HeaderTypeClient /* && headerType != HeaderTypeClientEncrypted */ {
|
||||||
return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType)
|
return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,8 +224,8 @@ func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.M
|
||||||
switch headerType {
|
switch headerType {
|
||||||
case HeaderTypeClient:
|
case HeaderTypeClient:
|
||||||
protocolConn.reader = reader
|
protocolConn.reader = reader
|
||||||
case HeaderTypeClientEncrypted:
|
// case HeaderTypeClientEncrypted:
|
||||||
protocolConn.reader = NewTLSEncryptedStreamReader(reader)
|
// protocolConn.reader = NewTLSEncryptedStreamReader(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.Protocol = "shadowsocks"
|
metadata.Protocol = "shadowsocks"
|
||||||
|
@ -240,7 +240,7 @@ type serverConn struct {
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
headerType byte
|
headerType byte
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
writer io.Writer
|
writer *shadowaead.Writer
|
||||||
requestSalt []byte
|
requestSalt []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,9 +275,9 @@ func (c *serverConn) writeResponse(payload []byte) (n int, err error) {
|
||||||
case HeaderTypeClient:
|
case HeaderTypeClient:
|
||||||
headerType = HeaderTypeServer
|
headerType = HeaderTypeServer
|
||||||
payloadLen = len(payload)
|
payloadLen = len(payload)
|
||||||
case HeaderTypeClientEncrypted:
|
// case HeaderTypeClientEncrypted:
|
||||||
headerType = HeaderTypeServerEncrypted
|
// headerType = HeaderTypeServerEncrypted
|
||||||
payloadLen = readTLSChunkEnd(payload)
|
// payloadLen = readTLSChunkEnd(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
_headerFixedChunk := buf.StackNewSize(1 + 8 + c.keySaltLength + 2)
|
_headerFixedChunk := buf.StackNewSize(1 + 8 + c.keySaltLength + 2)
|
||||||
|
@ -304,15 +304,15 @@ func (c *serverConn) writeResponse(payload []byte) (n int, err error) {
|
||||||
switch headerType {
|
switch headerType {
|
||||||
case HeaderTypeServer:
|
case HeaderTypeServer:
|
||||||
c.writer = writer
|
c.writer = writer
|
||||||
case HeaderTypeServerEncrypted:
|
// case HeaderTypeServerEncrypted:
|
||||||
encryptedWriter := NewTLSEncryptedStreamWriter(writer)
|
// encryptedWriter := NewTLSEncryptedStreamWriter(writer)
|
||||||
if payloadLen < len(payload) {
|
// if payloadLen < len(payload) {
|
||||||
_, err = encryptedWriter.Write(payload[payloadLen:])
|
// _, err = encryptedWriter.Write(payload[payloadLen:])
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
c.writer = encryptedWriter
|
// c.writer = encryptedWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
n = len(payload)
|
n = len(payload)
|
||||||
|
@ -336,6 +336,25 @@ func (c *serverConn) Write(p []byte) (n int, err error) {
|
||||||
return c.writeResponse(p)
|
return c.writeResponse(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *serverConn) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
|
if c.writer != nil {
|
||||||
|
return c.writer.WriteVectorised(buffers)
|
||||||
|
}
|
||||||
|
c.access.Lock()
|
||||||
|
if c.writer != nil {
|
||||||
|
c.access.Unlock()
|
||||||
|
return c.writer.WriteVectorised(buffers)
|
||||||
|
}
|
||||||
|
defer c.access.Unlock()
|
||||||
|
_, err := c.writeResponse(buffers[0].Bytes())
|
||||||
|
if err != nil {
|
||||||
|
buf.ReleaseMulti(buffers)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buffers[0].Release()
|
||||||
|
return c.writer.WriteVectorised(buffers[1:])
|
||||||
|
}
|
||||||
|
|
||||||
func (c *serverConn) ReadFrom(r io.Reader) (n int64, err error) {
|
func (c *serverConn) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
if c.writer == nil {
|
if c.writer == nil {
|
||||||
return bufio.ReadFrom0(c, r)
|
return bufio.ReadFrom0(c, r)
|
||||||
|
|
|
@ -183,7 +183,7 @@ func (s *MultiService[U]) newConnection(ctx context.Context, conn net.Conn, meta
|
||||||
return E.Cause(err, "read header")
|
return E.Cause(err, "read header")
|
||||||
}
|
}
|
||||||
|
|
||||||
if headerType != HeaderTypeClient && headerType != HeaderTypeClientEncrypted {
|
if headerType != HeaderTypeClient /*&& headerType != HeaderTypeClientEncrypted*/ {
|
||||||
return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType)
|
return E.Extend(ErrBadHeaderType, "expected ", HeaderTypeClient, ", got ", headerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,8 +240,8 @@ func (s *MultiService[U]) newConnection(ctx context.Context, conn net.Conn, meta
|
||||||
switch headerType {
|
switch headerType {
|
||||||
case HeaderTypeClient:
|
case HeaderTypeClient:
|
||||||
protocolConn.reader = reader
|
protocolConn.reader = reader
|
||||||
case HeaderTypeClientEncrypted:
|
// case HeaderTypeClientEncrypted:
|
||||||
protocolConn.reader = NewTLSEncryptedStreamReader(reader)
|
// protocolConn.reader = NewTLSEncryptedStreamReader(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.Protocol = "shadowsocks"
|
metadata.Protocol = "shadowsocks"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue