|
|
@@ -4,6 +4,9 @@ import (
|
|
|
"io"
|
|
|
|
|
|
"github.com/v2ray/v2ray-core/common/alloc"
|
|
|
+ "github.com/v2ray/v2ray-core/common/crypto"
|
|
|
+ "github.com/v2ray/v2ray-core/common/serial"
|
|
|
+ "github.com/v2ray/v2ray-core/transport"
|
|
|
)
|
|
|
|
|
|
// ReadFrom reads from a reader and put all content to a buffer.
|
|
|
@@ -17,6 +20,42 @@ func ReadFrom(reader io.Reader, buffer *alloc.Buffer) (*alloc.Buffer, error) {
|
|
|
return buffer, err
|
|
|
}
|
|
|
|
|
|
+func ReadChunk(reader io.Reader, buffer *alloc.Buffer) (*alloc.Buffer, error) {
|
|
|
+ if buffer == nil {
|
|
|
+ buffer = alloc.NewBuffer()
|
|
|
+ }
|
|
|
+ if _, err := io.ReadFull(reader, buffer.Value[:2]); err != nil {
|
|
|
+ alloc.Release(buffer)
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ length := serial.BytesLiteral(buffer.Value[:2]).Uint16Value()
|
|
|
+ if _, err := io.ReadFull(reader, buffer.Value[:length]); err != nil {
|
|
|
+ alloc.Release(buffer)
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ buffer.Slice(0, int(length))
|
|
|
+ return buffer, nil
|
|
|
+}
|
|
|
+
|
|
|
+func ReadAuthenticatedChunk(reader io.Reader, auth crypto.Authenticator, buffer *alloc.Buffer) (*alloc.Buffer, error) {
|
|
|
+ buffer, err := ReadChunk(reader, buffer)
|
|
|
+ if err != nil {
|
|
|
+ alloc.Release(buffer)
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ authSize := auth.AuthBytes()
|
|
|
+
|
|
|
+ authBytes := auth.Authenticate(nil, buffer.Value[authSize:])
|
|
|
+
|
|
|
+ if !serial.BytesLiteral(authBytes).Equals(serial.BytesLiteral(buffer.Value[:authSize])) {
|
|
|
+ alloc.Release(buffer)
|
|
|
+ return nil, transport.CorruptedPacket
|
|
|
+ }
|
|
|
+ buffer.SliceFrom(authSize)
|
|
|
+
|
|
|
+ return buffer, nil
|
|
|
+}
|
|
|
+
|
|
|
// ReaderToChan dumps all content from a given reader to a chan by constantly reading it until EOF.
|
|
|
func ReaderToChan(stream chan<- *alloc.Buffer, reader io.Reader) error {
|
|
|
allocate := alloc.NewBuffer
|