mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-02 15:36:41 -05:00
refactor io package
This commit is contained in:
parent
055023fdd5
commit
1948d0738f
@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/transport/internet"
|
"v2ray.com/core/transport/internet"
|
||||||
@ -63,8 +63,8 @@ type ProxyConnection struct {
|
|||||||
localAddr net.Addr
|
localAddr net.Addr
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
|
|
||||||
reader *v2io.ChanReader
|
reader *buf.BufferToBytesReader
|
||||||
writer *v2io.ChainWriter
|
writer *buf.BytesToBufferWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProxyConnection(src v2net.Address, dest v2net.Destination, stream ray.Ray) *ProxyConnection {
|
func NewProxyConnection(src v2net.Address, dest v2net.Destination, stream ray.Ray) *ProxyConnection {
|
||||||
@ -78,8 +78,8 @@ func NewProxyConnection(src v2net.Address, dest v2net.Destination, stream ray.Ra
|
|||||||
IP: []byte{0, 0, 0, 0},
|
IP: []byte{0, 0, 0, 0},
|
||||||
Port: 0,
|
Port: 0,
|
||||||
},
|
},
|
||||||
reader: v2io.NewChanReader(stream.InboundOutput()),
|
reader: buf.NewBytesReader(stream.InboundOutput()),
|
||||||
writer: v2io.NewChainWriter(stream.InboundInput()),
|
writer: buf.NewBytesWriter(stream.InboundInput()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,24 @@
|
|||||||
package buf
|
package buf
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"v2ray.com/core/common/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reader extends io.Reader with alloc.Buffer.
|
||||||
|
type Reader interface {
|
||||||
|
Release()
|
||||||
|
// Read reads content from underlying reader, and put it into an alloc.Buffer.
|
||||||
|
Read() (*Buffer, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writer extends io.Writer with alloc.Buffer.
|
||||||
|
type Writer interface {
|
||||||
|
Release()
|
||||||
|
// Write writes an alloc.Buffer into underlying writer.
|
||||||
|
Write(*Buffer) error
|
||||||
|
}
|
||||||
|
|
||||||
func ReadFrom(reader io.Reader) Supplier {
|
func ReadFrom(reader io.Reader) Supplier {
|
||||||
return func(b []byte) (int, error) {
|
return func(b []byte) (int, error) {
|
||||||
@ -13,3 +31,60 @@ func ReadFullFrom(reader io.Reader, size int) Supplier {
|
|||||||
return io.ReadFull(reader, b[:size])
|
return io.ReadFull(reader, b[:size])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pipe dumps all content from reader to writer, until an error happens.
|
||||||
|
func Pipe(reader Reader, writer Writer) error {
|
||||||
|
for {
|
||||||
|
buffer, err := reader.Read()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer.IsEmpty() {
|
||||||
|
buffer.Release()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writer.Write(buffer)
|
||||||
|
if err != nil {
|
||||||
|
buffer.Release()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PipeUntilEOF behaves the same as Pipe(). The only difference is PipeUntilEOF returns nil on EOF.
|
||||||
|
func PipeUntilEOF(reader Reader, writer Writer) error {
|
||||||
|
err := Pipe(reader, writer)
|
||||||
|
if err != nil && errors.Cause(err) != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader creates a new Reader.
|
||||||
|
// The Reader instance doesn't take the ownership of reader.
|
||||||
|
func NewReader(reader io.Reader) Reader {
|
||||||
|
return &BytesToBufferReader{
|
||||||
|
reader: reader,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBytesReader(stream Reader) *BufferToBytesReader {
|
||||||
|
return &BufferToBytesReader{
|
||||||
|
stream: stream,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWriter creates a new Writer.
|
||||||
|
func NewWriter(writer io.Writer) Writer {
|
||||||
|
return &BufferToBytesWriter{
|
||||||
|
writer: writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBytesWriter(writer Writer) *BytesToBufferWriter {
|
||||||
|
return &BytesToBufferWriter{
|
||||||
|
writer: writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
102
common/buf/reader.go
Normal file
102
common/buf/reader.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package buf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BytesToBufferReader is a Reader that adjusts its reading speed automatically.
|
||||||
|
type BytesToBufferReader struct {
|
||||||
|
reader io.Reader
|
||||||
|
largeBuffer *Buffer
|
||||||
|
highVolumn bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read implements Reader.Read().
|
||||||
|
func (v *BytesToBufferReader) Read() (*Buffer, error) {
|
||||||
|
if v.highVolumn && v.largeBuffer.IsEmpty() {
|
||||||
|
if v.largeBuffer == nil {
|
||||||
|
v.largeBuffer = NewLocal(32 * 1024)
|
||||||
|
}
|
||||||
|
err := v.largeBuffer.AppendSupplier(ReadFrom(v.reader))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if v.largeBuffer.Len() < Size {
|
||||||
|
v.highVolumn = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := New()
|
||||||
|
if !v.largeBuffer.IsEmpty() {
|
||||||
|
buffer.AppendSupplier(ReadFrom(v.largeBuffer))
|
||||||
|
return buffer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := buffer.AppendSupplier(ReadFrom(v.reader))
|
||||||
|
if err != nil {
|
||||||
|
buffer.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer.IsFull() {
|
||||||
|
v.highVolumn = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release implements Releasable.Release().
|
||||||
|
func (v *BytesToBufferReader) Release() {
|
||||||
|
v.reader = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BufferToBytesReader struct {
|
||||||
|
sync.Mutex
|
||||||
|
stream Reader
|
||||||
|
current *Buffer
|
||||||
|
eof bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Private: Visible for testing.
|
||||||
|
func (v *BufferToBytesReader) Fill() {
|
||||||
|
b, err := v.stream.Read()
|
||||||
|
v.current = b
|
||||||
|
if err != nil {
|
||||||
|
v.eof = true
|
||||||
|
v.current = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *BufferToBytesReader) Read(b []byte) (int, error) {
|
||||||
|
if v.eof {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Lock()
|
||||||
|
defer v.Unlock()
|
||||||
|
if v.current == nil {
|
||||||
|
v.Fill()
|
||||||
|
if v.eof {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nBytes, err := v.current.Read(b)
|
||||||
|
if v.current.IsEmpty() {
|
||||||
|
v.current.Release()
|
||||||
|
v.current = nil
|
||||||
|
}
|
||||||
|
return nBytes, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *BufferToBytesReader) Release() {
|
||||||
|
v.Lock()
|
||||||
|
defer v.Unlock()
|
||||||
|
|
||||||
|
v.eof = true
|
||||||
|
v.current.Release()
|
||||||
|
v.current = nil
|
||||||
|
v.stream = nil
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
package io_test
|
package buf_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
. "v2ray.com/core/common/buf"
|
||||||
. "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,12 +14,12 @@ func TestAdaptiveReader(t *testing.T) {
|
|||||||
rawContent := make([]byte, 1024*1024)
|
rawContent := make([]byte, 1024*1024)
|
||||||
buffer := bytes.NewBuffer(rawContent)
|
buffer := bytes.NewBuffer(rawContent)
|
||||||
|
|
||||||
reader := NewAdaptiveReader(buffer)
|
reader := NewReader(buffer)
|
||||||
b1, err := reader.Read()
|
b1, err := reader.Read()
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
assert.Bool(b1.IsFull()).IsTrue()
|
assert.Bool(b1.IsFull()).IsTrue()
|
||||||
assert.Int(b1.Len()).Equals(buf.Size)
|
assert.Int(b1.Len()).Equals(Size)
|
||||||
assert.Int(buffer.Len()).Equals(cap(rawContent) - buf.Size)
|
assert.Int(buffer.Len()).Equals(cap(rawContent) - Size)
|
||||||
|
|
||||||
b2, err := reader.Read()
|
b2, err := reader.Read()
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
68
common/buf/writer.go
Normal file
68
common/buf/writer.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package buf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BufferToBytesWriter is a Writer that writes alloc.Buffer into underlying writer.
|
||||||
|
type BufferToBytesWriter struct {
|
||||||
|
writer io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write implements Writer.Write(). Write() takes ownership of the given buffer.
|
||||||
|
func (v *BufferToBytesWriter) Write(buffer *Buffer) error {
|
||||||
|
defer buffer.Release()
|
||||||
|
for {
|
||||||
|
nBytes, err := v.writer.Write(buffer.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if nBytes == buffer.Len() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buffer.SliceFrom(nBytes)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release implements Releasable.Release().
|
||||||
|
func (v *BufferToBytesWriter) Release() {
|
||||||
|
v.writer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type BytesToBufferWriter struct {
|
||||||
|
sync.Mutex
|
||||||
|
writer Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *BytesToBufferWriter) Write(payload []byte) (int, error) {
|
||||||
|
v.Lock()
|
||||||
|
defer v.Unlock()
|
||||||
|
if v.writer == nil {
|
||||||
|
return 0, io.ErrClosedPipe
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesWritten := 0
|
||||||
|
size := len(payload)
|
||||||
|
for size > 0 {
|
||||||
|
buffer := New()
|
||||||
|
nBytes, _ := buffer.Write(payload)
|
||||||
|
size -= nBytes
|
||||||
|
payload = payload[nBytes:]
|
||||||
|
bytesWritten += nBytes
|
||||||
|
err := v.writer.Write(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return bytesWritten, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytesWritten, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *BytesToBufferWriter) Release() {
|
||||||
|
v.Lock()
|
||||||
|
v.writer.Release()
|
||||||
|
v.writer = nil
|
||||||
|
v.Unlock()
|
||||||
|
}
|
@ -1,26 +1,26 @@
|
|||||||
package io_test
|
package buf_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
. "v2ray.com/core/common/buf"
|
||||||
. "v2ray.com/core/common/io"
|
"v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAdaptiveWriter(t *testing.T) {
|
func TestWriter(t *testing.T) {
|
||||||
assert := assert.On(t)
|
assert := assert.On(t)
|
||||||
|
|
||||||
lb := buf.New()
|
lb := New()
|
||||||
lb.AppendSupplier(buf.ReadFrom(rand.Reader))
|
lb.AppendSupplier(ReadFrom(rand.Reader))
|
||||||
|
|
||||||
expectedBytes := append([]byte(nil), lb.Bytes()...)
|
expectedBytes := append([]byte(nil), lb.Bytes()...)
|
||||||
|
|
||||||
writeBuffer := bytes.NewBuffer(make([]byte, 0, 1024*1024))
|
writeBuffer := bytes.NewBuffer(make([]byte, 0, 1024*1024))
|
||||||
|
|
||||||
writer := NewAdaptiveWriter(NewBufferedWriter(writeBuffer))
|
writer := NewWriter(bufio.NewWriter(writeBuffer))
|
||||||
err := writer.Write(lb)
|
err := writer.Write(lb)
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
assert.Bytes(expectedBytes).Equals(writeBuffer.Bytes())
|
assert.Bytes(expectedBytes).Equals(writeBuffer.Bytes())
|
@ -1,4 +1,4 @@
|
|||||||
package io
|
package bufio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
@ -14,7 +14,7 @@ type BufferedReader struct {
|
|||||||
cached bool
|
cached bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBufferedReader(rawReader io.Reader) *BufferedReader {
|
func NewReader(rawReader io.Reader) *BufferedReader {
|
||||||
return &BufferedReader{
|
return &BufferedReader{
|
||||||
reader: rawReader,
|
reader: rawReader,
|
||||||
buffer: buf.New(),
|
buffer: buf.New(),
|
@ -1,11 +1,11 @@
|
|||||||
package io_test
|
package bufio_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
. "v2ray.com/core/common/io"
|
. "v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ func TestBufferedReader(t *testing.T) {
|
|||||||
|
|
||||||
len := content.Len()
|
len := content.Len()
|
||||||
|
|
||||||
reader := NewBufferedReader(content)
|
reader := NewReader(content)
|
||||||
assert.Bool(reader.Cached()).IsTrue()
|
assert.Bool(reader.Cached()).IsTrue()
|
||||||
|
|
||||||
payload := make([]byte, 16)
|
payload := make([]byte, 16)
|
@ -1,4 +1,4 @@
|
|||||||
package io
|
package bufio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
@ -15,7 +15,7 @@ type BufferedWriter struct {
|
|||||||
cached bool
|
cached bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBufferedWriter(rawWriter io.Writer) *BufferedWriter {
|
func NewWriter(rawWriter io.Writer) *BufferedWriter {
|
||||||
return &BufferedWriter{
|
return &BufferedWriter{
|
||||||
writer: rawWriter,
|
writer: rawWriter,
|
||||||
buffer: buf.NewSmall(),
|
buffer: buf.NewSmall(),
|
@ -1,11 +1,11 @@
|
|||||||
package io_test
|
package bufio_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
. "v2ray.com/core/common/io"
|
. "v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ func TestBufferedWriter(t *testing.T) {
|
|||||||
|
|
||||||
content := buf.New()
|
content := buf.New()
|
||||||
|
|
||||||
writer := NewBufferedWriter(content)
|
writer := NewWriter(content)
|
||||||
assert.Bool(writer.Cached()).IsTrue()
|
assert.Bool(writer.Cached()).IsTrue()
|
||||||
|
|
||||||
payload := make([]byte, 16)
|
payload := make([]byte, 16)
|
||||||
@ -34,7 +34,7 @@ func TestBufferedWriterLargePayload(t *testing.T) {
|
|||||||
|
|
||||||
content := buf.NewLocal(128 * 1024)
|
content := buf.NewLocal(128 * 1024)
|
||||||
|
|
||||||
writer := NewBufferedWriter(content)
|
writer := NewWriter(content)
|
||||||
assert.Bool(writer.Cached()).IsTrue()
|
assert.Bool(writer.Cached()).IsTrue()
|
||||||
|
|
||||||
payload := make([]byte, 64*1024)
|
payload := make([]byte, 64*1024)
|
15
common/bufio/bufio.go
Normal file
15
common/bufio/bufio.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Package bufio is a replacement of the standard golang package bufio.
|
||||||
|
package bufio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func OriginalReader(reader io.Reader) *bufio.Reader {
|
||||||
|
return bufio.NewReader(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func OriginalReaderSize(reader io.Reader, size int) *bufio.Reader {
|
||||||
|
return bufio.NewReaderSize(reader, size)
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"v2ray.com/core/common/errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
package io
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ChainWriter struct {
|
|
||||||
sync.Mutex
|
|
||||||
writer Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewChainWriter(writer Writer) *ChainWriter {
|
|
||||||
return &ChainWriter{
|
|
||||||
writer: writer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ChainWriter) Write(payload []byte) (int, error) {
|
|
||||||
v.Lock()
|
|
||||||
defer v.Unlock()
|
|
||||||
if v.writer == nil {
|
|
||||||
return 0, io.ErrClosedPipe
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesWritten := 0
|
|
||||||
size := len(payload)
|
|
||||||
for size > 0 {
|
|
||||||
buffer := buf.New()
|
|
||||||
nBytes, _ := buffer.Write(payload)
|
|
||||||
size -= nBytes
|
|
||||||
payload = payload[nBytes:]
|
|
||||||
bytesWritten += nBytes
|
|
||||||
err := v.writer.Write(buffer)
|
|
||||||
if err != nil {
|
|
||||||
return bytesWritten, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesWritten, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ChainWriter) Release() {
|
|
||||||
v.Lock()
|
|
||||||
v.writer.Release()
|
|
||||||
v.writer = nil
|
|
||||||
v.Unlock()
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
package io
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ChanReader struct {
|
|
||||||
sync.Mutex
|
|
||||||
stream Reader
|
|
||||||
current *buf.Buffer
|
|
||||||
eof bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewChanReader(stream Reader) *ChanReader {
|
|
||||||
return &ChanReader{
|
|
||||||
stream: stream,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private: Visible for testing.
|
|
||||||
func (v *ChanReader) Fill() {
|
|
||||||
b, err := v.stream.Read()
|
|
||||||
v.current = b
|
|
||||||
if err != nil {
|
|
||||||
v.eof = true
|
|
||||||
v.current = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ChanReader) Read(b []byte) (int, error) {
|
|
||||||
if v.eof {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Lock()
|
|
||||||
defer v.Unlock()
|
|
||||||
if v.current == nil {
|
|
||||||
v.Fill()
|
|
||||||
if v.eof {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nBytes, err := v.current.Read(b)
|
|
||||||
if v.current.IsEmpty() {
|
|
||||||
v.current.Release()
|
|
||||||
v.current = nil
|
|
||||||
}
|
|
||||||
return nBytes, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ChanReader) Release() {
|
|
||||||
v.Lock()
|
|
||||||
defer v.Unlock()
|
|
||||||
|
|
||||||
v.eof = true
|
|
||||||
v.current.Release()
|
|
||||||
v.current = nil
|
|
||||||
v.stream = nil
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package io
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/common/buf"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reader extends io.Reader with alloc.Buffer.
|
|
||||||
type Reader interface {
|
|
||||||
common.Releasable
|
|
||||||
// Read reads content from underlying reader, and put it into an alloc.Buffer.
|
|
||||||
Read() (*buf.Buffer, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdaptiveReader is a Reader that adjusts its reading speed automatically.
|
|
||||||
type AdaptiveReader struct {
|
|
||||||
reader io.Reader
|
|
||||||
largeBuffer *buf.Buffer
|
|
||||||
highVolumn bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAdaptiveReader creates a new AdaptiveReader.
|
|
||||||
// The AdaptiveReader instance doesn't take the ownership of reader.
|
|
||||||
func NewAdaptiveReader(reader io.Reader) *AdaptiveReader {
|
|
||||||
return &AdaptiveReader{
|
|
||||||
reader: reader,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read implements Reader.Read().
|
|
||||||
func (v *AdaptiveReader) Read() (*buf.Buffer, error) {
|
|
||||||
if v.highVolumn && v.largeBuffer.IsEmpty() {
|
|
||||||
if v.largeBuffer == nil {
|
|
||||||
v.largeBuffer = buf.NewLocal(32 * 1024)
|
|
||||||
}
|
|
||||||
err := v.largeBuffer.AppendSupplier(buf.ReadFrom(v.reader))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if v.largeBuffer.Len() < buf.Size {
|
|
||||||
v.highVolumn = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := buf.New()
|
|
||||||
if !v.largeBuffer.IsEmpty() {
|
|
||||||
buffer.AppendSupplier(buf.ReadFrom(v.largeBuffer))
|
|
||||||
return buffer, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := buffer.AppendSupplier(buf.ReadFrom(v.reader))
|
|
||||||
if err != nil {
|
|
||||||
buffer.Release()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer.IsFull() {
|
|
||||||
v.highVolumn = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release implements Releasable.Release().
|
|
||||||
func (v *AdaptiveReader) Release() {
|
|
||||||
v.reader = nil
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package io
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"v2ray.com/core/common/errors"
|
|
||||||
"v2ray.com/core/common/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Pipe dumps all content from reader to writer, until an error happens.
|
|
||||||
func Pipe(reader Reader, writer Writer) error {
|
|
||||||
for {
|
|
||||||
buffer, err := reader.Read()
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("IO: Pipe exits as ", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer.IsEmpty() {
|
|
||||||
buffer.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = writer.Write(buffer)
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("IO: Pipe exits as ", err)
|
|
||||||
buffer.Release()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PipeUntilEOF behaves the same as Pipe(). The only difference is PipeUntilEOF returns nil on EOF.
|
|
||||||
func PipeUntilEOF(reader Reader, writer Writer) error {
|
|
||||||
err := Pipe(reader, writer)
|
|
||||||
if err != nil && errors.Cause(err) != io.EOF {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package io
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/common/buf"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Writer extends io.Writer with alloc.Buffer.
|
|
||||||
type Writer interface {
|
|
||||||
common.Releasable
|
|
||||||
// Write writes an alloc.Buffer into underlying writer.
|
|
||||||
Write(*buf.Buffer) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdaptiveWriter is a Writer that writes alloc.Buffer into underlying writer.
|
|
||||||
type AdaptiveWriter struct {
|
|
||||||
writer io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAdaptiveWriter creates a new AdaptiveWriter.
|
|
||||||
func NewAdaptiveWriter(writer io.Writer) *AdaptiveWriter {
|
|
||||||
return &AdaptiveWriter{
|
|
||||||
writer: writer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write implements Writer.Write(). Write() takes ownership of the given buffer.
|
|
||||||
func (v *AdaptiveWriter) Write(buffer *buf.Buffer) error {
|
|
||||||
defer buffer.Release()
|
|
||||||
for {
|
|
||||||
nBytes, err := v.writer.Write(buffer.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if nBytes == buffer.Len() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buffer.SliceFrom(nBytes)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release implements Releasable.Release().
|
|
||||||
func (v *AdaptiveWriter) Release() {
|
|
||||||
v.writer = nil
|
|
||||||
}
|
|
@ -1,12 +1,8 @@
|
|||||||
package serial
|
package serial
|
||||||
|
|
||||||
import (
|
import "hash"
|
||||||
"hash"
|
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
func WriteHash(h hash.Hash) func([]byte) (int, error) {
|
||||||
)
|
|
||||||
|
|
||||||
func WriteHash(h hash.Hash) buf.Supplier {
|
|
||||||
return func(b []byte) (int, error) {
|
return func(b []byte) (int, error) {
|
||||||
h.Sum(b[:0])
|
h.Sum(b[:0])
|
||||||
return h.Size(), nil
|
return h.Size(), nil
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package serial
|
package serial
|
||||||
|
|
||||||
import (
|
import "strconv"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Uint16ToBytes(value uint16, b []byte) []byte {
|
func Uint16ToBytes(value uint16, b []byte) []byte {
|
||||||
return append(b, byte(value>>8), byte(value))
|
return append(b, byte(value>>8), byte(value))
|
||||||
@ -14,7 +10,7 @@ func Uint16ToString(value uint16) string {
|
|||||||
return strconv.Itoa(int(value))
|
return strconv.Itoa(int(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteUint16(value uint16) buf.Supplier {
|
func WriteUint16(value uint16) func([]byte) (int, error) {
|
||||||
return func(b []byte) (int, error) {
|
return func(b []byte) (int, error) {
|
||||||
b = Uint16ToBytes(value, b[:0])
|
b = Uint16ToBytes(value, b[:0])
|
||||||
return 2, nil
|
return 2, nil
|
||||||
@ -29,7 +25,7 @@ func Uint32ToString(value uint32) string {
|
|||||||
return strconv.FormatUint(uint64(value), 10)
|
return strconv.FormatUint(uint64(value), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteUint32(value uint32) buf.Supplier {
|
func WriteUint32(value uint32) func([]byte) (int, error) {
|
||||||
return func(b []byte) (int, error) {
|
return func(b []byte) (int, error) {
|
||||||
b = Uint32ToBytes(value, b[:0])
|
b = Uint32ToBytes(value, b[:0])
|
||||||
return 4, nil
|
return 4, nil
|
||||||
|
@ -3,8 +3,6 @@ package serial
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ToString(v interface{}) string {
|
func ToString(v interface{}) string {
|
||||||
@ -36,7 +34,7 @@ func Concat(v ...interface{}) string {
|
|||||||
return strings.Join(values, "")
|
return strings.Join(values, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteString(s string) buf.Supplier {
|
func WriteString(s string) func([]byte) (int, error) {
|
||||||
return func(b []byte) (int, error) {
|
return func(b []byte) (int, error) {
|
||||||
return copy(b, []byte(s)), nil
|
return copy(b, []byte(s)), nil
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package blackhole
|
package blackhole
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"v2ray.com/core/common/buf"
|
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/ptypes"
|
"github.com/golang/protobuf/ptypes"
|
||||||
"github.com/golang/protobuf/ptypes/any"
|
"github.com/golang/protobuf/ptypes/any"
|
||||||
|
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,17 +20,17 @@ Content-Length: 0
|
|||||||
|
|
||||||
type ResponseConfig interface {
|
type ResponseConfig interface {
|
||||||
AsAny() *any.Any
|
AsAny() *any.Any
|
||||||
WriteTo(v2io.Writer)
|
WriteTo(buf.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *NoneResponse) WriteTo(v2io.Writer) {}
|
func (v *NoneResponse) WriteTo(buf.Writer) {}
|
||||||
|
|
||||||
func (v *NoneResponse) AsAny() *any.Any {
|
func (v *NoneResponse) AsAny() *any.Any {
|
||||||
r, _ := ptypes.MarshalAny(v)
|
r, _ := ptypes.MarshalAny(v)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *HTTPResponse) WriteTo(writer v2io.Writer) {
|
func (v *HTTPResponse) WriteTo(writer buf.Writer) {
|
||||||
b := buf.NewLocal(512)
|
b := buf.NewLocal(512)
|
||||||
b.AppendSupplier(serial.WriteString(http403response))
|
b.AppendSupplier(serial.WriteString(http403response))
|
||||||
writer.Write(b)
|
writer.Write(b)
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
. "v2ray.com/core/proxy/blackhole"
|
. "v2ray.com/core/proxy/blackhole"
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
)
|
)
|
||||||
@ -17,7 +16,7 @@ func TestHTTPResponse(t *testing.T) {
|
|||||||
buffer := buf.New()
|
buffer := buf.New()
|
||||||
|
|
||||||
httpResponse := new(HTTPResponse)
|
httpResponse := new(HTTPResponse)
|
||||||
httpResponse.WriteTo(v2io.NewAdaptiveWriter(buffer))
|
httpResponse.WriteTo(buf.NewWriter(buffer))
|
||||||
|
|
||||||
reader := bufio.NewReader(buffer)
|
reader := bufio.NewReader(buffer)
|
||||||
response, err := http.ReadResponse(reader, nil)
|
response, err := http.ReadResponse(reader, nil)
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"v2ray.com/core/app/dispatcher"
|
"v2ray.com/core/app/dispatcher"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/loader"
|
"v2ray.com/core/common/loader"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
@ -176,10 +175,10 @@ func (v *DokodemoDoor) HandleTCPConnection(conn internet.Connection) {
|
|||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
v2reader := v2io.NewAdaptiveReader(reader)
|
v2reader := buf.NewReader(reader)
|
||||||
defer v2reader.Release()
|
defer v2reader.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(v2reader, ray.InboundInput()); err != nil {
|
if err := buf.PipeUntilEOF(v2reader, ray.InboundInput()); err != nil {
|
||||||
log.Info("Dokodemo: Failed to transport all TCP request: ", err)
|
log.Info("Dokodemo: Failed to transport all TCP request: ", err)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@ -188,10 +187,10 @@ func (v *DokodemoDoor) HandleTCPConnection(conn internet.Connection) {
|
|||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
v2writer := v2io.NewAdaptiveWriter(conn)
|
v2writer := buf.NewWriter(conn)
|
||||||
defer v2writer.Release()
|
defer v2writer.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(ray.InboundOutput(), v2writer); err != nil {
|
if err := buf.PipeUntilEOF(ray.InboundOutput(), v2writer); err != nil {
|
||||||
log.Info("Dokodemo: Failed to transport all TCP response: ", err)
|
log.Info("Dokodemo: Failed to transport all TCP response: ", err)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
|
@ -2,12 +2,12 @@ package freedom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/app/dns"
|
"v2ray.com/core/app/dns"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/dice"
|
"v2ray.com/core/common/dice"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/loader"
|
"v2ray.com/core/common/loader"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
@ -100,10 +100,10 @@ func (v *FreedomConnection) Dispatch(destination v2net.Destination, payload *buf
|
|||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
v2writer := v2io.NewAdaptiveWriter(conn)
|
v2writer := buf.NewWriter(conn)
|
||||||
defer v2writer.Release()
|
defer v2writer.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(input, v2writer); err != nil {
|
if err := buf.PipeUntilEOF(input, v2writer); err != nil {
|
||||||
log.Info("Freedom: Failed to transport all TCP request: ", err)
|
log.Info("Freedom: Failed to transport all TCP request: ", err)
|
||||||
}
|
}
|
||||||
if tcpConn, ok := conn.(*tcp.RawConnection); ok {
|
if tcpConn, ok := conn.(*tcp.RawConnection); ok {
|
||||||
@ -121,8 +121,8 @@ func (v *FreedomConnection) Dispatch(destination v2net.Destination, payload *buf
|
|||||||
reader = v2net.NewTimeOutReader(timeout /* seconds */, conn)
|
reader = v2net.NewTimeOutReader(timeout /* seconds */, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
v2reader := v2io.NewAdaptiveReader(reader)
|
v2reader := buf.NewReader(reader)
|
||||||
if err := v2io.PipeUntilEOF(v2reader, output); err != nil {
|
if err := buf.PipeUntilEOF(v2reader, output); err != nil {
|
||||||
log.Info("Freedom: Failed to transport all TCP response: ", err)
|
log.Info("Freedom: Failed to transport all TCP response: ", err)
|
||||||
}
|
}
|
||||||
v2reader.Release()
|
v2reader.Release()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -12,8 +11,9 @@ import (
|
|||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/app/dispatcher"
|
"v2ray.com/core/app/dispatcher"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/loader"
|
"v2ray.com/core/common/loader"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
@ -98,7 +98,7 @@ func parseHost(rawHost string, defaultPort v2net.Port) (v2net.Destination, error
|
|||||||
func (v *Server) handleConnection(conn internet.Connection) {
|
func (v *Server) handleConnection(conn internet.Connection) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
timedReader := v2net.NewTimeOutReader(v.config.Timeout, conn)
|
timedReader := v2net.NewTimeOutReader(v.config.Timeout, conn)
|
||||||
reader := bufio.NewReaderSize(timedReader, 2048)
|
reader := bufio.OriginalReaderSize(timedReader, 2048)
|
||||||
|
|
||||||
request, err := http.ReadRequest(reader)
|
request, err := http.ReadRequest(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -158,10 +158,10 @@ func (v *Server) transport(input io.Reader, output io.Writer, ray ray.InboundRay
|
|||||||
defer wg.Wait()
|
defer wg.Wait()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
v2reader := v2io.NewAdaptiveReader(input)
|
v2reader := buf.NewReader(input)
|
||||||
defer v2reader.Release()
|
defer v2reader.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(v2reader, ray.InboundInput()); err != nil {
|
if err := buf.PipeUntilEOF(v2reader, ray.InboundInput()); err != nil {
|
||||||
log.Info("HTTP: Failed to transport all TCP request: ", err)
|
log.Info("HTTP: Failed to transport all TCP request: ", err)
|
||||||
}
|
}
|
||||||
ray.InboundInput().Close()
|
ray.InboundInput().Close()
|
||||||
@ -169,10 +169,10 @@ func (v *Server) transport(input io.Reader, output io.Writer, ray ray.InboundRay
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
v2writer := v2io.NewAdaptiveWriter(output)
|
v2writer := buf.NewWriter(output)
|
||||||
defer v2writer.Release()
|
defer v2writer.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(ray.InboundOutput(), v2writer); err != nil {
|
if err := buf.PipeUntilEOF(ray.InboundOutput(), v2writer); err != nil {
|
||||||
log.Info("HTTP: Failed to transport all TCP response: ", err)
|
log.Info("HTTP: Failed to transport all TCP response: ", err)
|
||||||
}
|
}
|
||||||
ray.InboundOutput().Release()
|
ray.InboundOutput().Release()
|
||||||
@ -221,7 +221,7 @@ func (v *Server) GenerateResponse(statusCode int, status string) *http.Response
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionInfo, reader *bufio.Reader, writer io.Writer) {
|
func (v *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionInfo, reader io.Reader, writer io.Writer) {
|
||||||
if len(request.URL.Host) <= 0 {
|
if len(request.URL.Host) <= 0 {
|
||||||
response := v.GenerateResponse(400, "Bad Request")
|
response := v.GenerateResponse(400, "Bad Request")
|
||||||
response.Write(writer)
|
response.Write(writer)
|
||||||
@ -240,7 +240,7 @@ func (v *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionIn
|
|||||||
finish.Add(1)
|
finish.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer finish.Done()
|
defer finish.Done()
|
||||||
requestWriter := v2io.NewBufferedWriter(v2io.NewChainWriter(ray.InboundInput()))
|
requestWriter := bufio.NewWriter(buf.NewBytesWriter(ray.InboundInput()))
|
||||||
err := request.Write(requestWriter)
|
err := request.Write(requestWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warning("HTTP: Failed to write request: ", err)
|
log.Warning("HTTP: Failed to write request: ", err)
|
||||||
@ -252,13 +252,13 @@ func (v *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionIn
|
|||||||
finish.Add(1)
|
finish.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer finish.Done()
|
defer finish.Done()
|
||||||
responseReader := bufio.NewReader(v2io.NewChanReader(ray.InboundOutput()))
|
responseReader := bufio.OriginalReader(buf.NewBytesReader(ray.InboundOutput()))
|
||||||
response, err := http.ReadResponse(responseReader, request)
|
response, err := http.ReadResponse(responseReader, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warning("HTTP: Failed to read response: ", err)
|
log.Warning("HTTP: Failed to read response: ", err)
|
||||||
response = v.GenerateResponse(503, "Service Unavailable")
|
response = v.GenerateResponse(503, "Service Unavailable")
|
||||||
}
|
}
|
||||||
responseWriter := v2io.NewBufferedWriter(writer)
|
responseWriter := bufio.NewWriter(writer)
|
||||||
err = response.Write(responseWriter)
|
err = response.Write(responseWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warning("HTTP: Failed to write response: ", err)
|
log.Warning("HTTP: Failed to write response: ", err)
|
||||||
|
@ -2,9 +2,10 @@ package shadowsocks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
v2io "v2ray.com/core/common/io"
|
"v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
@ -87,7 +88,7 @@ func (v *Client) Dispatch(destination v2net.Destination, payload *buf.Buffer, ra
|
|||||||
}
|
}
|
||||||
|
|
||||||
if request.Command == protocol.RequestCommandTCP {
|
if request.Command == protocol.RequestCommandTCP {
|
||||||
bufferedWriter := v2io.NewBufferedWriter(conn)
|
bufferedWriter := bufio.NewWriter(conn)
|
||||||
defer bufferedWriter.Release()
|
defer bufferedWriter.Release()
|
||||||
|
|
||||||
bodyWriter, err := WriteTCPRequest(request, bufferedWriter)
|
bodyWriter, err := WriteTCPRequest(request, bufferedWriter)
|
||||||
@ -115,13 +116,13 @@ func (v *Client) Dispatch(destination v2net.Destination, payload *buf.Buffer, ra
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(responseReader, ray.OutboundOutput()); err != nil {
|
if err := buf.PipeUntilEOF(responseReader, ray.OutboundOutput()); err != nil {
|
||||||
log.Info("Shadowsocks|Client: Failed to transport all TCP response: ", err)
|
log.Info("Shadowsocks|Client: Failed to transport all TCP response: ", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
bufferedWriter.SetCached(false)
|
bufferedWriter.SetCached(false)
|
||||||
if err := v2io.PipeUntilEOF(ray.OutboundInput(), bodyWriter); err != nil {
|
if err := buf.PipeUntilEOF(ray.OutboundInput(), bodyWriter); err != nil {
|
||||||
log.Info("Shadowsocks|Client: Failed to trasnport all TCP request: ", err)
|
log.Info("Shadowsocks|Client: Failed to trasnport all TCP request: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ func (v *Client) Dispatch(destination v2net.Destination, payload *buf.Buffer, ra
|
|||||||
User: user,
|
User: user,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(reader, ray.OutboundOutput()); err != nil {
|
if err := buf.PipeUntilEOF(reader, ray.OutboundOutput()); err != nil {
|
||||||
log.Info("Shadowsocks|Client: Failed to transport all UDP response: ", err)
|
log.Info("Shadowsocks|Client: Failed to transport all UDP response: ", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -156,7 +157,7 @@ func (v *Client) Dispatch(destination v2net.Destination, payload *buf.Buffer, ra
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := v2io.PipeUntilEOF(ray.OutboundInput(), writer); err != nil {
|
if err := buf.PipeUntilEOF(ray.OutboundInput(), writer); err != nil {
|
||||||
log.Info("Shadowsocks|Client: Failed to transport all UDP request: ", err)
|
log.Info("Shadowsocks|Client: Failed to transport all UDP request: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/crypto"
|
"v2ray.com/core/common/crypto"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
@ -23,7 +22,7 @@ const (
|
|||||||
AddrTypeDomain = 3
|
AddrTypeDomain = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHeader, v2io.Reader, error) {
|
func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
|
||||||
rawAccount, err := user.GetTypedAccount()
|
rawAccount, err := user.GetTypedAccount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
|
return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
|
||||||
@ -121,17 +120,17 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var chunkReader v2io.Reader
|
var chunkReader buf.Reader
|
||||||
if request.Option.Has(RequestOptionOneTimeAuth) {
|
if request.Option.Has(RequestOptionOneTimeAuth) {
|
||||||
chunkReader = NewChunkReader(reader, NewAuthenticator(ChunkKeyGenerator(iv)))
|
chunkReader = NewChunkReader(reader, NewAuthenticator(ChunkKeyGenerator(iv)))
|
||||||
} else {
|
} else {
|
||||||
chunkReader = v2io.NewAdaptiveReader(reader)
|
chunkReader = buf.NewReader(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
return request, chunkReader, nil
|
return request, chunkReader, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (v2io.Writer, error) {
|
func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
|
||||||
user := request.User
|
user := request.User
|
||||||
rawAccount, err := user.GetTypedAccount()
|
rawAccount, err := user.GetTypedAccount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -183,17 +182,17 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (v2io.Wr
|
|||||||
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to write header.")
|
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to write header.")
|
||||||
}
|
}
|
||||||
|
|
||||||
var chunkWriter v2io.Writer
|
var chunkWriter buf.Writer
|
||||||
if request.Option.Has(RequestOptionOneTimeAuth) {
|
if request.Option.Has(RequestOptionOneTimeAuth) {
|
||||||
chunkWriter = NewChunkWriter(writer, NewAuthenticator(ChunkKeyGenerator(iv)))
|
chunkWriter = NewChunkWriter(writer, NewAuthenticator(ChunkKeyGenerator(iv)))
|
||||||
} else {
|
} else {
|
||||||
chunkWriter = v2io.NewAdaptiveWriter(writer)
|
chunkWriter = buf.NewWriter(writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunkWriter, nil
|
return chunkWriter, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadTCPResponse(user *protocol.User, reader io.Reader) (v2io.Reader, error) {
|
func ReadTCPResponse(user *protocol.User, reader io.Reader) (buf.Reader, error) {
|
||||||
rawAccount, err := user.GetTypedAccount()
|
rawAccount, err := user.GetTypedAccount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
|
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.")
|
||||||
@ -210,10 +209,10 @@ func ReadTCPResponse(user *protocol.User, reader io.Reader) (v2io.Reader, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to initialize decoding stream.")
|
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to initialize decoding stream.")
|
||||||
}
|
}
|
||||||
return v2io.NewAdaptiveReader(crypto.NewCryptionReader(stream, reader)), nil
|
return buf.NewReader(crypto.NewCryptionReader(stream, reader)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (v2io.Writer, error) {
|
func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
|
||||||
user := request.User
|
user := request.User
|
||||||
rawAccount, err := user.GetTypedAccount()
|
rawAccount, err := user.GetTypedAccount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -233,7 +232,7 @@ func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (v2io.W
|
|||||||
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to create encoding stream.")
|
return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to create encoding stream.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return v2io.NewAdaptiveWriter(crypto.NewCryptionWriter(stream, writer)), nil
|
return buf.NewWriter(crypto.NewCryptionWriter(stream, writer)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncodeUDPPacket(request *protocol.RequestHeader, payload *buf.Buffer) (*buf.Buffer, error) {
|
func EncodeUDPPacket(request *protocol.RequestHeader, payload *buf.Buffer) (*buf.Buffer, error) {
|
||||||
|
@ -3,12 +3,13 @@ package shadowsocks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/app/dispatcher"
|
"v2ray.com/core/app/dispatcher"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
@ -150,7 +151,7 @@ func (v *Server) handleConnection(conn internet.Connection) {
|
|||||||
timedReader := v2net.NewTimeOutReader(16, conn)
|
timedReader := v2net.NewTimeOutReader(16, conn)
|
||||||
defer timedReader.Release()
|
defer timedReader.Release()
|
||||||
|
|
||||||
bufferedReader := v2io.NewBufferedReader(timedReader)
|
bufferedReader := bufio.NewReader(timedReader)
|
||||||
defer bufferedReader.Release()
|
defer bufferedReader.Release()
|
||||||
|
|
||||||
request, bodyReader, err := ReadTCPSession(v.user, bufferedReader)
|
request, bodyReader, err := ReadTCPSession(v.user, bufferedReader)
|
||||||
@ -183,7 +184,7 @@ func (v *Server) handleConnection(conn internet.Connection) {
|
|||||||
go func() {
|
go func() {
|
||||||
defer writeFinish.Unlock()
|
defer writeFinish.Unlock()
|
||||||
|
|
||||||
bufferedWriter := v2io.NewBufferedWriter(conn)
|
bufferedWriter := bufio.NewWriter(conn)
|
||||||
defer bufferedWriter.Release()
|
defer bufferedWriter.Release()
|
||||||
|
|
||||||
responseWriter, err := WriteTCPResponse(request, bufferedWriter)
|
responseWriter, err := WriteTCPResponse(request, bufferedWriter)
|
||||||
@ -197,13 +198,13 @@ func (v *Server) handleConnection(conn internet.Connection) {
|
|||||||
responseWriter.Write(payload)
|
responseWriter.Write(payload)
|
||||||
bufferedWriter.SetCached(false)
|
bufferedWriter.SetCached(false)
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(ray.InboundOutput(), responseWriter); err != nil {
|
if err := buf.PipeUntilEOF(ray.InboundOutput(), responseWriter); err != nil {
|
||||||
log.Info("Shadowsocks|Server: Failed to transport all TCP response: ", err)
|
log.Info("Shadowsocks|Server: Failed to transport all TCP response: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(bodyReader, ray.InboundInput()); err != nil {
|
if err := buf.PipeUntilEOF(bodyReader, ray.InboundInput()); err != nil {
|
||||||
log.Info("Shadowsocks|Server: Failed to transport all TCP request: ", err)
|
log.Info("Shadowsocks|Server: Failed to transport all TCP request: ", err)
|
||||||
}
|
}
|
||||||
ray.InboundInput().Close()
|
ray.InboundInput().Close()
|
||||||
|
@ -7,9 +7,10 @@ import (
|
|||||||
|
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/app/dispatcher"
|
"v2ray.com/core/app/dispatcher"
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/common/crypto"
|
"v2ray.com/core/common/crypto"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/loader"
|
"v2ray.com/core/common/loader"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
@ -106,10 +107,10 @@ func (v *Server) handleConnection(connection internet.Connection) {
|
|||||||
defer connection.Close()
|
defer connection.Close()
|
||||||
|
|
||||||
timedReader := v2net.NewTimeOutReader(v.config.Timeout, connection)
|
timedReader := v2net.NewTimeOutReader(v.config.Timeout, connection)
|
||||||
reader := v2io.NewBufferedReader(timedReader)
|
reader := bufio.NewReader(timedReader)
|
||||||
defer reader.Release()
|
defer reader.Release()
|
||||||
|
|
||||||
writer := v2io.NewBufferedWriter(connection)
|
writer := bufio.NewWriter(connection)
|
||||||
defer writer.Release()
|
defer writer.Release()
|
||||||
|
|
||||||
auth, auth4, err := protocol.ReadAuthentication(reader)
|
auth, auth4, err := protocol.ReadAuthentication(reader)
|
||||||
@ -128,7 +129,7 @@ func (v *Server) handleConnection(connection internet.Connection) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Server) handleSocks5(clientAddr v2net.Destination, reader *v2io.BufferedReader, writer *v2io.BufferedWriter, auth protocol.Socks5AuthenticationRequest) error {
|
func (v *Server) handleSocks5(clientAddr v2net.Destination, reader *bufio.BufferedReader, writer *bufio.BufferedWriter, auth protocol.Socks5AuthenticationRequest) error {
|
||||||
expectedAuthMethod := protocol.AuthNotRequired
|
expectedAuthMethod := protocol.AuthNotRequired
|
||||||
if v.config.AuthType == AuthType_PASSWORD {
|
if v.config.AuthType == AuthType_PASSWORD {
|
||||||
expectedAuthMethod = protocol.AuthUserPass
|
expectedAuthMethod = protocol.AuthUserPass
|
||||||
@ -232,7 +233,7 @@ func (v *Server) handleSocks5(clientAddr v2net.Destination, reader *v2io.Buffere
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Server) handleUDP(reader io.Reader, writer *v2io.BufferedWriter) error {
|
func (v *Server) handleUDP(reader io.Reader, writer *bufio.BufferedWriter) error {
|
||||||
response := protocol.NewSocks5Response()
|
response := protocol.NewSocks5Response()
|
||||||
response.Error = protocol.ErrorSuccess
|
response.Error = protocol.ErrorSuccess
|
||||||
|
|
||||||
@ -264,7 +265,7 @@ func (v *Server) handleUDP(reader io.Reader, writer *v2io.BufferedWriter) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Server) handleSocks4(clientAddr v2net.Destination, reader *v2io.BufferedReader, writer *v2io.BufferedWriter, auth protocol.Socks4AuthenticationRequest) error {
|
func (v *Server) handleSocks4(clientAddr v2net.Destination, reader *bufio.BufferedReader, writer *bufio.BufferedWriter, auth protocol.Socks4AuthenticationRequest) error {
|
||||||
result := protocol.Socks4RequestGranted
|
result := protocol.Socks4RequestGranted
|
||||||
if auth.Command == protocol.CmdBind {
|
if auth.Command == protocol.CmdBind {
|
||||||
result = protocol.Socks4RequestRejected
|
result = protocol.Socks4RequestRejected
|
||||||
@ -302,19 +303,19 @@ func (v *Server) transport(reader io.Reader, writer io.Writer, session *proxy.Se
|
|||||||
defer output.Release()
|
defer output.Release()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
v2reader := v2io.NewAdaptiveReader(reader)
|
v2reader := buf.NewReader(reader)
|
||||||
defer v2reader.Release()
|
defer v2reader.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(v2reader, input); err != nil {
|
if err := buf.PipeUntilEOF(v2reader, input); err != nil {
|
||||||
log.Info("Socks|Server: Failed to transport all TCP request: ", err)
|
log.Info("Socks|Server: Failed to transport all TCP request: ", err)
|
||||||
}
|
}
|
||||||
input.Close()
|
input.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
v2writer := v2io.NewAdaptiveWriter(writer)
|
v2writer := buf.NewWriter(writer)
|
||||||
defer v2writer.Release()
|
defer v2writer.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(output, v2writer); err != nil {
|
if err := buf.PipeUntilEOF(output, v2writer); err != nil {
|
||||||
log.Info("Socks|Server: Failed to transport all TCP response: ", err)
|
log.Info("Socks|Server: Failed to transport all TCP response: ", err)
|
||||||
}
|
}
|
||||||
output.Release()
|
output.Release()
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"v2ray.com/core/app/dispatcher"
|
"v2ray.com/core/app/dispatcher"
|
||||||
v2io "v2ray.com/core/common/io"
|
"v2ray.com/core/common/buf"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
)
|
)
|
||||||
@ -49,19 +49,19 @@ func (v *InboundConnectionHandler) Communicate(destination v2net.Destination) er
|
|||||||
writeFinish.Lock()
|
writeFinish.Lock()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
v2reader := v2io.NewAdaptiveReader(v.ConnInput)
|
v2reader := buf.NewReader(v.ConnInput)
|
||||||
defer v2reader.Release()
|
defer v2reader.Release()
|
||||||
|
|
||||||
v2io.Pipe(v2reader, input)
|
buf.Pipe(v2reader, input)
|
||||||
input.Close()
|
input.Close()
|
||||||
readFinish.Unlock()
|
readFinish.Unlock()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
v2writer := v2io.NewAdaptiveWriter(v.ConnOutput)
|
v2writer := buf.NewWriter(v.ConnOutput)
|
||||||
defer v2writer.Release()
|
defer v2writer.Release()
|
||||||
|
|
||||||
v2io.Pipe(output, v2writer)
|
buf.Pipe(output, v2writer)
|
||||||
output.Release()
|
output.Release()
|
||||||
writeFinish.Unlock()
|
writeFinish.Unlock()
|
||||||
}()
|
}()
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/proxy"
|
"v2ray.com/core/proxy"
|
||||||
"v2ray.com/core/transport/ray"
|
"v2ray.com/core/transport/ray"
|
||||||
@ -33,20 +32,20 @@ func (v *OutboundConnectionHandler) Dispatch(destination v2net.Destination, payl
|
|||||||
writeFinish.Lock()
|
writeFinish.Lock()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
v2writer := v2io.NewAdaptiveWriter(v.ConnOutput)
|
v2writer := buf.NewWriter(v.ConnOutput)
|
||||||
defer v2writer.Release()
|
defer v2writer.Release()
|
||||||
|
|
||||||
v2io.Pipe(input, v2writer)
|
buf.Pipe(input, v2writer)
|
||||||
writeFinish.Unlock()
|
writeFinish.Unlock()
|
||||||
input.Release()
|
input.Release()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
writeFinish.Lock()
|
writeFinish.Lock()
|
||||||
|
|
||||||
v2reader := v2io.NewAdaptiveReader(v.ConnInput)
|
v2reader := buf.NewReader(v.ConnInput)
|
||||||
defer v2reader.Release()
|
defer v2reader.Release()
|
||||||
|
|
||||||
v2io.Pipe(v2reader, output)
|
buf.Pipe(v2reader, output)
|
||||||
output.Close()
|
output.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
|
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/crypto"
|
"v2ray.com/core/common/crypto"
|
||||||
"v2ray.com/core/common/dice"
|
"v2ray.com/core/common/dice"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
@ -109,7 +109,7 @@ func (v *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) v2io.Writer {
|
func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
|
||||||
var authWriter io.Writer
|
var authWriter io.Writer
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
@ -162,7 +162,7 @@ func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
|
|||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer)
|
authWriter = crypto.NewAuthenticationWriter(auth, writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
return v2io.NewAdaptiveWriter(authWriter)
|
return buf.NewWriter(authWriter)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ func (v *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
|
|||||||
return header, nil
|
return header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, reader io.Reader) v2io.Reader {
|
func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
|
||||||
aggressive := (request.Command == protocol.RequestCommandTCP)
|
aggressive := (request.Command == protocol.RequestCommandTCP)
|
||||||
var authReader io.Reader
|
var authReader io.Reader
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
@ -256,7 +256,7 @@ func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
|
|||||||
authReader = crypto.NewAuthenticationReader(auth, reader, aggressive)
|
authReader = crypto.NewAuthenticationReader(auth, reader, aggressive)
|
||||||
}
|
}
|
||||||
|
|
||||||
return v2io.NewAdaptiveReader(authReader)
|
return buf.NewReader(authReader)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChunkNonceGenerator struct {
|
type ChunkNonceGenerator struct {
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
|
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/crypto"
|
"v2ray.com/core/common/crypto"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/protocol"
|
"v2ray.com/core/common/protocol"
|
||||||
@ -155,7 +155,7 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
|||||||
return request, nil
|
return request, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) v2io.Reader {
|
func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
|
||||||
aggressive := (request.Command == protocol.RequestCommandTCP)
|
aggressive := (request.Command == protocol.RequestCommandTCP)
|
||||||
var authReader io.Reader
|
var authReader io.Reader
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
@ -209,7 +209,7 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
|||||||
authReader = crypto.NewAuthenticationReader(auth, reader, aggressive)
|
authReader = crypto.NewAuthenticationReader(auth, reader, aggressive)
|
||||||
}
|
}
|
||||||
|
|
||||||
return v2io.NewAdaptiveReader(authReader)
|
return buf.NewReader(authReader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) {
|
func (v *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) {
|
||||||
@ -229,7 +229,7 @@ func (v *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) v2io.Writer {
|
func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
|
||||||
var authWriter io.Writer
|
var authWriter io.Writer
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
@ -280,5 +280,5 @@ func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
|||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer)
|
authWriter = crypto.NewAuthenticationWriter(auth, writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
return v2io.NewAdaptiveWriter(authWriter)
|
return buf.NewWriter(authWriter)
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
"v2ray.com/core/app/proxyman"
|
"v2ray.com/core/app/proxyman"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
"v2ray.com/core/common/loader"
|
"v2ray.com/core/common/loader"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
@ -139,7 +139,7 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
|
|||||||
connReader := v2net.NewTimeOutReader(8, connection)
|
connReader := v2net.NewTimeOutReader(8, connection)
|
||||||
defer connReader.Release()
|
defer connReader.Release()
|
||||||
|
|
||||||
reader := v2io.NewBufferedReader(connReader)
|
reader := bufio.NewReader(connReader)
|
||||||
defer reader.Release()
|
defer reader.Release()
|
||||||
|
|
||||||
v.RLock()
|
v.RLock()
|
||||||
@ -186,7 +186,7 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
bodyReader := session.DecodeRequestBody(request, reader)
|
bodyReader := session.DecodeRequestBody(request, reader)
|
||||||
if err := v2io.PipeUntilEOF(bodyReader, input); err != nil {
|
if err := buf.PipeUntilEOF(bodyReader, input); err != nil {
|
||||||
connection.SetReusable(false)
|
connection.SetReusable(false)
|
||||||
}
|
}
|
||||||
bodyReader.Release()
|
bodyReader.Release()
|
||||||
@ -195,7 +195,7 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
|
|||||||
readFinish.Unlock()
|
readFinish.Unlock()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
writer := v2io.NewBufferedWriter(connection)
|
writer := bufio.NewWriter(connection)
|
||||||
defer writer.Release()
|
defer writer.Release()
|
||||||
|
|
||||||
response := &protocol.ResponseHeader{
|
response := &protocol.ResponseHeader{
|
||||||
@ -218,7 +218,7 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
|
|||||||
|
|
||||||
writer.SetCached(false)
|
writer.SetCached(false)
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(output, bodyWriter); err != nil {
|
if err := buf.PipeUntilEOF(output, bodyWriter); err != nil {
|
||||||
connection.SetReusable(false)
|
connection.SetReusable(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"v2ray.com/core/app"
|
"v2ray.com/core/app"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
v2io "v2ray.com/core/common/io"
|
"v2ray.com/core/common/bufio"
|
||||||
"v2ray.com/core/common/loader"
|
"v2ray.com/core/common/loader"
|
||||||
"v2ray.com/core/common/log"
|
"v2ray.com/core/common/log"
|
||||||
v2net "v2ray.com/core/common/net"
|
v2net "v2ray.com/core/common/net"
|
||||||
@ -92,10 +92,10 @@ func (v *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *buf.B
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, payload *buf.Buffer, input v2io.Reader, finish *sync.Mutex) {
|
func (v *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, payload *buf.Buffer, input buf.Reader, finish *sync.Mutex) {
|
||||||
defer finish.Unlock()
|
defer finish.Unlock()
|
||||||
|
|
||||||
writer := v2io.NewBufferedWriter(conn)
|
writer := bufio.NewWriter(conn)
|
||||||
defer writer.Release()
|
defer writer.Release()
|
||||||
session.EncodeRequestHeader(request, writer)
|
session.EncodeRequestHeader(request, writer)
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ func (v *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, co
|
|||||||
}
|
}
|
||||||
writer.SetCached(false)
|
writer.SetCached(false)
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(input, bodyWriter); err != nil {
|
if err := buf.PipeUntilEOF(input, bodyWriter); err != nil {
|
||||||
conn.SetReusable(false)
|
conn.SetReusable(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,10 +124,10 @@ func (v *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, co
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VMessOutboundHandler) handleResponse(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, dest v2net.Destination, output v2io.Writer, finish *sync.Mutex) {
|
func (v *VMessOutboundHandler) handleResponse(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, dest v2net.Destination, output buf.Writer, finish *sync.Mutex) {
|
||||||
defer finish.Unlock()
|
defer finish.Unlock()
|
||||||
|
|
||||||
reader := v2io.NewBufferedReader(conn)
|
reader := bufio.NewReader(conn)
|
||||||
defer reader.Release()
|
defer reader.Release()
|
||||||
|
|
||||||
header, err := session.DecodeResponseHeader(reader)
|
header, err := session.DecodeResponseHeader(reader)
|
||||||
@ -146,7 +146,7 @@ func (v *VMessOutboundHandler) handleResponse(session *encoding.ClientSession, c
|
|||||||
bodyReader := session.DecodeResponseBody(request, reader)
|
bodyReader := session.DecodeResponseBody(request, reader)
|
||||||
defer bodyReader.Release()
|
defer bodyReader.Release()
|
||||||
|
|
||||||
if err := v2io.PipeUntilEOF(bodyReader, output); err != nil {
|
if err := buf.PipeUntilEOF(bodyReader, output); err != nil {
|
||||||
conn.SetReusable(false)
|
conn.SetReusable(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package ray
|
package ray
|
||||||
|
|
||||||
import (
|
import "v2ray.com/core/common/buf"
|
||||||
v2io "v2ray.com/core/common/io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OutboundRay is a transport interface for outbound connections.
|
// OutboundRay is a transport interface for outbound connections.
|
||||||
type OutboundRay interface {
|
type OutboundRay interface {
|
||||||
@ -36,11 +34,11 @@ type Ray interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type InputStream interface {
|
type InputStream interface {
|
||||||
v2io.Reader
|
buf.Reader
|
||||||
Close()
|
Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutputStream interface {
|
type OutputStream interface {
|
||||||
v2io.Writer
|
buf.Writer
|
||||||
Close()
|
Close()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user