mirror of https://github.com/v2ray/v2ray-core
refactor multibuffer
parent
0f324a613e
commit
842a089dad
|
@ -32,12 +32,10 @@ func TestStatsWriter(t *testing.T) {
|
||||||
Writer: buf.Discard,
|
Writer: buf.Discard,
|
||||||
}
|
}
|
||||||
|
|
||||||
var mb buf.MultiBuffer
|
mb := buf.MergeBytes(nil, []byte("abcd"))
|
||||||
common.Must2(mb.Write([]byte("abcd")))
|
|
||||||
common.Must(writer.WriteMultiBuffer(mb))
|
common.Must(writer.WriteMultiBuffer(mb))
|
||||||
|
|
||||||
mb = buf.ReleaseMulti(mb)
|
mb = buf.MergeBytes(nil, []byte("efg"))
|
||||||
common.Must2(mb.Write([]byte("efg")))
|
|
||||||
common.Must(writer.WriteMultiBuffer(mb))
|
common.Must(writer.WriteMultiBuffer(mb))
|
||||||
|
|
||||||
if c.Value() != 7 {
|
if c.Value() != 7 {
|
||||||
|
|
|
@ -251,8 +251,7 @@ func (w *PortalWorker) heartbeat() error {
|
||||||
|
|
||||||
b, err := proto.Marshal(msg)
|
b, err := proto.Marshal(msg)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
var mb buf.MultiBuffer
|
mb := buf.MergeBytes(nil, b)
|
||||||
common.Must2(mb.Write(b))
|
|
||||||
return w.writer.WriteMultiBuffer(mb)
|
return w.writer.WriteMultiBuffer(mb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,21 +8,9 @@ import (
|
||||||
"v2ray.com/core/common/serial"
|
"v2ray.com/core/common/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReadAllToMultiBuffer reads all content from the reader into a MultiBuffer, until EOF.
|
|
||||||
func ReadAllToMultiBuffer(reader io.Reader) (MultiBuffer, error) {
|
|
||||||
mb := make(MultiBuffer, 0, 128)
|
|
||||||
|
|
||||||
if _, err := mb.ReadFrom(reader); err != nil {
|
|
||||||
ReleaseMulti(mb)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return mb, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadAllToBytes reads all content from the reader into a byte array, until EOF.
|
// ReadAllToBytes reads all content from the reader into a byte array, until EOF.
|
||||||
func ReadAllToBytes(reader io.Reader) ([]byte, error) {
|
func ReadAllToBytes(reader io.Reader) ([]byte, error) {
|
||||||
mb, err := ReadAllToMultiBuffer(reader)
|
mb, err := ReadFrom(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -30,7 +18,8 @@ func ReadAllToBytes(reader io.Reader) ([]byte, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
b := make([]byte, mb.Len())
|
b := make([]byte, mb.Len())
|
||||||
common.Must2(mb.Read(b))
|
mb, _, err = SplitBytes(mb, b)
|
||||||
|
common.Must(err)
|
||||||
ReleaseMulti(mb)
|
ReleaseMulti(mb)
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
@ -47,6 +36,23 @@ func MergeMulti(dest MultiBuffer, src MultiBuffer) (MultiBuffer, MultiBuffer) {
|
||||||
return dest, src[:0]
|
return dest, src[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MergeBytes(dest MultiBuffer, src []byte) MultiBuffer {
|
||||||
|
n := len(dest)
|
||||||
|
if n > 0 && !(dest)[n-1].IsFull() {
|
||||||
|
nBytes, _ := (dest)[n-1].Write(src)
|
||||||
|
src = src[nBytes:]
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(src) > 0 {
|
||||||
|
b := New()
|
||||||
|
nBytes, _ := b.Write(src)
|
||||||
|
src = src[nBytes:]
|
||||||
|
dest = append(dest, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest
|
||||||
|
}
|
||||||
|
|
||||||
// ReleaseMulti release all content of the MultiBuffer, and returns an empty MultiBuffer.
|
// ReleaseMulti release all content of the MultiBuffer, and returns an empty MultiBuffer.
|
||||||
func ReleaseMulti(mb MultiBuffer) MultiBuffer {
|
func ReleaseMulti(mb MultiBuffer) MultiBuffer {
|
||||||
for i := range mb {
|
for i := range mb {
|
||||||
|
@ -69,93 +75,42 @@ func (mb MultiBuffer) Copy(b []byte) int {
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFrom implements io.ReaderFrom.
|
// ReadFrom reads all content from reader until EOF.
|
||||||
func (mb *MultiBuffer) ReadFrom(reader io.Reader) (int64, error) {
|
func ReadFrom(reader io.Reader) (MultiBuffer, error) {
|
||||||
totalBytes := int64(0)
|
mb := make(MultiBuffer, 0, 16)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
b := New()
|
b := New()
|
||||||
_, err := b.ReadFullFrom(reader, Size)
|
_, err := b.ReadFullFrom(reader, Size)
|
||||||
if b.IsEmpty() {
|
if b.IsEmpty() {
|
||||||
b.Release()
|
b.Release()
|
||||||
} else {
|
} else {
|
||||||
*mb = append(*mb, b)
|
mb = append(mb, b)
|
||||||
}
|
}
|
||||||
totalBytes += int64(b.Len())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) == io.EOF || errors.Cause(err) == io.ErrUnexpectedEOF {
|
if errors.Cause(err) == io.EOF || errors.Cause(err) == io.ErrUnexpectedEOF {
|
||||||
return totalBytes, nil
|
return mb, nil
|
||||||
}
|
}
|
||||||
return totalBytes, err
|
return mb, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read implements io.Reader.
|
func SplitBytes(mb MultiBuffer, b []byte) (MultiBuffer, int, error) {
|
||||||
func (mb *MultiBuffer) Read(b []byte) (int, error) {
|
|
||||||
if mb.IsEmpty() {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
endIndex := len(*mb)
|
|
||||||
totalBytes := 0
|
totalBytes := 0
|
||||||
for i, bb := range *mb {
|
|
||||||
|
for len(mb) > 0 {
|
||||||
|
bb := mb[0]
|
||||||
nBytes, _ := bb.Read(b)
|
nBytes, _ := bb.Read(b)
|
||||||
totalBytes += nBytes
|
totalBytes += nBytes
|
||||||
b = b[nBytes:]
|
b = b[nBytes:]
|
||||||
if bb.IsEmpty() {
|
if !bb.IsEmpty() {
|
||||||
bb.Release()
|
|
||||||
(*mb)[i] = nil
|
|
||||||
} else {
|
|
||||||
endIndex = i
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
bb.Release()
|
||||||
*mb = (*mb)[endIndex:]
|
mb = mb[1:]
|
||||||
return totalBytes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteTo implements io.WriterTo.
|
|
||||||
func (mb *MultiBuffer) WriteTo(writer io.Writer) (int64, error) {
|
|
||||||
defer func() {
|
|
||||||
*mb = ReleaseMulti(*mb)
|
|
||||||
}()
|
|
||||||
|
|
||||||
totalBytes := int64(0)
|
|
||||||
for _, b := range *mb {
|
|
||||||
nBytes, err := writer.Write(b.Bytes())
|
|
||||||
totalBytes += int64(nBytes)
|
|
||||||
if err != nil {
|
|
||||||
return totalBytes, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalBytes, nil
|
return mb, totalBytes, nil
|
||||||
}
|
|
||||||
|
|
||||||
// Write implements io.Writer.
|
|
||||||
func (mb *MultiBuffer) Write(b []byte) (int, error) {
|
|
||||||
totalBytes := len(b)
|
|
||||||
|
|
||||||
n := len(*mb)
|
|
||||||
if n > 0 && !(*mb)[n-1].IsFull() {
|
|
||||||
nBytes, _ := (*mb)[n-1].Write(b)
|
|
||||||
b = b[nBytes:]
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(b) > 0 {
|
|
||||||
bb := New()
|
|
||||||
nBytes, _ := bb.Write(b)
|
|
||||||
b = b[nBytes:]
|
|
||||||
*mb = append(*mb, bb)
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalBytes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteMultiBuffer implements Writer.
|
|
||||||
func (mb *MultiBuffer) WriteMultiBuffer(b MultiBuffer) error {
|
|
||||||
*mb, _ = MergeMulti(*mb, b)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the total number of bytes in the MultiBuffer.
|
// Len returns the total number of bytes in the MultiBuffer.
|
||||||
|
@ -223,3 +178,39 @@ func (mb *MultiBuffer) SplitFirst() *Buffer {
|
||||||
*mb = (*mb)[1:]
|
*mb = (*mb)[1:]
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MultiBufferContainer struct {
|
||||||
|
MultiBuffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MultiBufferContainer) Read(b []byte) (int, error) {
|
||||||
|
if c.MultiBuffer.IsEmpty() {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
mb, nBytes, err := SplitBytes(c.MultiBuffer, b)
|
||||||
|
c.MultiBuffer = mb
|
||||||
|
return nBytes, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MultiBufferContainer) ReadMultiBuffer() (MultiBuffer, error) {
|
||||||
|
mb := c.MultiBuffer
|
||||||
|
c.MultiBuffer = nil
|
||||||
|
return mb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MultiBufferContainer) Write(b []byte) (int, error) {
|
||||||
|
c.MultiBuffer = MergeBytes(c.MultiBuffer, b)
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error {
|
||||||
|
mb, _ := MergeMulti(c.MultiBuffer, b)
|
||||||
|
c.MultiBuffer = mb
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MultiBufferContainer) Close() error {
|
||||||
|
c.MultiBuffer = ReleaseMulti(c.MultiBuffer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ func TestMultiBufferRead(t *testing.T) {
|
||||||
mb := MultiBuffer{b1, b2}
|
mb := MultiBuffer{b1, b2}
|
||||||
|
|
||||||
bs := make([]byte, 32)
|
bs := make([]byte, 32)
|
||||||
nBytes, err := mb.Read(bs)
|
_, nBytes, err := SplitBytes(mb, bs)
|
||||||
assert(err, IsNil)
|
assert(err, IsNil)
|
||||||
assert(nBytes, Equals, 4)
|
assert(nBytes, Equals, 4)
|
||||||
assert(bs[:nBytes], Equals, []byte("abcd"))
|
assert(bs[:nBytes], Equals, []byte("abcd"))
|
||||||
|
@ -43,16 +43,8 @@ func TestMultiBufferSliceBySizeLarge(t *testing.T) {
|
||||||
lb := make([]byte, 8*1024)
|
lb := make([]byte, 8*1024)
|
||||||
common.Must2(io.ReadFull(rand.Reader, lb))
|
common.Must2(io.ReadFull(rand.Reader, lb))
|
||||||
|
|
||||||
var mb MultiBuffer
|
mb := MergeBytes(nil, lb)
|
||||||
common.Must2(mb.Write(lb))
|
|
||||||
|
|
||||||
mb2 := mb.SliceBySize(1024)
|
mb2 := mb.SliceBySize(1024)
|
||||||
assert(mb2.Len(), Equals, int32(1024))
|
assert(mb2.Len(), Equals, int32(1024))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInterface(t *testing.T) {
|
|
||||||
assert := With(t)
|
|
||||||
|
|
||||||
assert((*MultiBuffer)(nil), Implements, (*io.WriterTo)(nil))
|
|
||||||
assert((*MultiBuffer)(nil), Implements, (*io.ReaderFrom)(nil))
|
|
||||||
}
|
|
||||||
|
|
|
@ -46,8 +46,9 @@ func (r *BufferedReader) ReadByte() (byte, error) {
|
||||||
// Read implements io.Reader. It reads from internal buffer first (if available) and then reads from the underlying reader.
|
// Read implements io.Reader. It reads from internal buffer first (if available) and then reads from the underlying reader.
|
||||||
func (r *BufferedReader) Read(b []byte) (int, error) {
|
func (r *BufferedReader) Read(b []byte) (int, error) {
|
||||||
if !r.Buffer.IsEmpty() {
|
if !r.Buffer.IsEmpty() {
|
||||||
nBytes, err := r.Buffer.Read(b)
|
buffer, nBytes, err := SplitBytes(r.Buffer, b)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
r.Buffer = buffer
|
||||||
if r.Buffer.IsEmpty() {
|
if r.Buffer.IsEmpty() {
|
||||||
r.Buffer = nil
|
r.Buffer = nil
|
||||||
}
|
}
|
||||||
|
@ -59,12 +60,12 @@ func (r *BufferedReader) Read(b []byte) (int, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
nBytes, err := mb.Read(b)
|
mb, nBytes, err := SplitBytes(mb, b)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if !mb.IsEmpty() {
|
if !mb.IsEmpty() {
|
||||||
r.Buffer = mb
|
r.Buffer = mb
|
||||||
}
|
}
|
||||||
return nBytes, err
|
return nBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadMultiBuffer implements Reader.
|
// ReadMultiBuffer implements Reader.
|
||||||
|
|
|
@ -69,8 +69,7 @@ func TestReadByte(t *testing.T) {
|
||||||
t.Error("unexpected byte: ", b, " want a")
|
t.Error("unexpected byte: ", b, " want a")
|
||||||
}
|
}
|
||||||
|
|
||||||
var mb MultiBuffer
|
nBytes, err := reader.WriteTo(DiscardBytes)
|
||||||
nBytes, err := reader.WriteTo(&mb)
|
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if nBytes != 3 {
|
if nBytes != 3 {
|
||||||
t.Error("unexpect bytes written: ", nBytes)
|
t.Error("unexpect bytes written: ", nBytes)
|
||||||
|
|
|
@ -33,8 +33,7 @@ func TestReadvReader(t *testing.T) {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
writer := NewWriter(conn)
|
writer := NewWriter(conn)
|
||||||
var mb MultiBuffer
|
mb := MergeBytes(nil, data)
|
||||||
common.Must2(mb.Write(data))
|
|
||||||
|
|
||||||
if err := writer.WriteMultiBuffer(mb); err != nil {
|
if err := writer.WriteMultiBuffer(mb); err != nil {
|
||||||
t.Fatal("failed to write data: ", err)
|
t.Fatal("failed to write data: ", err)
|
||||||
|
@ -58,7 +57,8 @@ func TestReadvReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rdata := make([]byte, size)
|
rdata := make([]byte, size)
|
||||||
common.Must2(rmb.Read(rdata))
|
_, _, err = SplitBytes(rmb, rdata)
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
if err := compare.BytesEqualWithDetail(data, rdata); err != nil {
|
if err := compare.BytesEqualWithDetail(data, rdata); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -134,15 +134,16 @@ func (w *BufferedWriter) WriteMultiBuffer(b MultiBuffer) error {
|
||||||
return w.writer.WriteMultiBuffer(b)
|
return w.writer.WriteMultiBuffer(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer ReleaseMulti(b)
|
reader := MultiBufferContainer{
|
||||||
|
MultiBuffer: b,
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
for !b.IsEmpty() {
|
for !reader.MultiBuffer.IsEmpty() {
|
||||||
if w.buffer == nil {
|
if w.buffer == nil {
|
||||||
w.buffer = New()
|
w.buffer = New()
|
||||||
}
|
}
|
||||||
if _, err := w.buffer.ReadFrom(&b); err != nil {
|
common.Must2(w.buffer.ReadFrom(&reader))
|
||||||
return err
|
|
||||||
}
|
|
||||||
if w.buffer.IsFull() {
|
if w.buffer.IsFull() {
|
||||||
if err := w.flushInternal(); err != nil {
|
if err := w.flushInternal(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -194,7 +194,7 @@ func (r *AuthenticationReader) readInternal(soft bool, mb *buf.MultiBuffer) erro
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
common.Must2(mb.Write(rb))
|
*mb = buf.MergeBytes(*mb, rb)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,11 +279,17 @@ func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error {
|
||||||
payloadSize := buf.Size - int32(w.auth.Overhead()) - w.sizeParser.SizeBytes() - maxPadding
|
payloadSize := buf.Size - int32(w.auth.Overhead()) - w.sizeParser.SizeBytes() - maxPadding
|
||||||
mb2Write := make(buf.MultiBuffer, 0, len(mb)+10)
|
mb2Write := make(buf.MultiBuffer, 0, len(mb)+10)
|
||||||
|
|
||||||
|
temp := buf.New()
|
||||||
|
defer temp.Release()
|
||||||
|
|
||||||
|
rawBytes := temp.Extend(payloadSize)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
b := buf.New()
|
nb, nBytes, err := buf.SplitBytes(mb, rawBytes)
|
||||||
common.Must2(b.ReadFrom(io.LimitReader(&mb, int64(payloadSize))))
|
common.Must(err)
|
||||||
eb, err := w.seal(b.Bytes())
|
mb = nb
|
||||||
b.Release()
|
|
||||||
|
eb, err := w.seal(rawBytes[:nBytes])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buf.ReleaseMulti(mb2Write)
|
buf.ReleaseMulti(mb2Write)
|
||||||
|
|
|
@ -30,8 +30,7 @@ func TestAuthenticationReaderWriter(t *testing.T) {
|
||||||
rawPayload := make([]byte, payloadSize)
|
rawPayload := make([]byte, payloadSize)
|
||||||
rand.Read(rawPayload)
|
rand.Read(rawPayload)
|
||||||
|
|
||||||
var payload buf.MultiBuffer
|
payload := buf.MergeBytes(nil, rawPayload)
|
||||||
payload.Write(rawPayload)
|
|
||||||
assert(payload.Len(), Equals, int32(payloadSize))
|
assert(payload.Len(), Equals, int32(payloadSize))
|
||||||
|
|
||||||
cache := bytes.NewBuffer(nil)
|
cache := bytes.NewBuffer(nil)
|
||||||
|
@ -66,7 +65,7 @@ func TestAuthenticationReaderWriter(t *testing.T) {
|
||||||
assert(mb.Len(), Equals, int32(payloadSize))
|
assert(mb.Len(), Equals, int32(payloadSize))
|
||||||
|
|
||||||
mbContent := make([]byte, payloadSize)
|
mbContent := make([]byte, payloadSize)
|
||||||
mb.Read(mbContent)
|
buf.SplitBytes(mb, mbContent)
|
||||||
assert(mbContent, Equals, rawPayload)
|
assert(mbContent, Equals, rawPayload)
|
||||||
|
|
||||||
_, err = reader.ReadMultiBuffer()
|
_, err = reader.ReadMultiBuffer()
|
||||||
|
|
|
@ -100,7 +100,7 @@ func (c *connection) Write(b []byte) (int, error) {
|
||||||
|
|
||||||
l := len(b)
|
l := len(b)
|
||||||
mb := make(buf.MultiBuffer, 0, l/buf.Size+1)
|
mb := make(buf.MultiBuffer, 0, l/buf.Size+1)
|
||||||
common.Must2(mb.Write(b))
|
mb = buf.MergeBytes(mb, b)
|
||||||
return l, c.writer.WriteMultiBuffer(mb)
|
return l, c.writer.WriteMultiBuffer(mb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
|
||||||
return nil, newError("v2ctl doesn't exist").Base(err)
|
return nil, newError("v2ctl doesn't exist").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
errBuffer := buf.MultiBuffer{}
|
var errBuffer buf.MultiBufferContainer
|
||||||
outBuffer := buf.MultiBuffer{}
|
var outBuffer buf.MultiBufferContainer
|
||||||
|
|
||||||
cmd := exec.Command(v2ctl, args...)
|
cmd := exec.Command(v2ctl, args...)
|
||||||
cmd.Stderr = &errBuffer
|
cmd.Stderr = &errBuffer
|
||||||
|
@ -35,12 +35,10 @@ func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
|
||||||
if err := cmd.Wait(); err != nil {
|
if err := cmd.Wait(); err != nil {
|
||||||
msg := "failed to execute v2ctl"
|
msg := "failed to execute v2ctl"
|
||||||
if errBuffer.Len() > 0 {
|
if errBuffer.Len() > 0 {
|
||||||
msg += ": " + errBuffer.String()
|
msg += ": " + errBuffer.MultiBuffer.String()
|
||||||
}
|
}
|
||||||
buf.ReleaseMulti(errBuffer)
|
|
||||||
buf.ReleaseMulti(outBuffer)
|
|
||||||
return nil, newError(msg).Base(err)
|
return nil, newError(msg).Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return outBuffer, nil
|
return outBuffer.MultiBuffer, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,6 @@ import (
|
||||||
|
|
||||||
//go:generate errorgen
|
//go:generate errorgen
|
||||||
|
|
||||||
type ClosableMultiBuffer struct {
|
|
||||||
buf.MultiBuffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClosableMultiBuffer) Close() error {
|
|
||||||
buf.ReleaseMulti(c.MultiBuffer)
|
|
||||||
c.MultiBuffer = nil
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadConfigFile(configFile string) (io.ReadCloser, error) {
|
func loadConfigFile(configFile string) (io.ReadCloser, error) {
|
||||||
if configFile == "stdin:" {
|
if configFile == "stdin:" {
|
||||||
return os.Stdin, nil
|
return os.Stdin, nil
|
||||||
|
@ -32,7 +22,9 @@ func loadConfigFile(configFile string) (io.ReadCloser, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ClosableMultiBuffer{content}, nil
|
return &buf.MultiBufferContainer{
|
||||||
|
MultiBuffer: content,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedFile := os.ExpandEnv(configFile)
|
fixedFile := os.ExpandEnv(configFile)
|
||||||
|
@ -42,12 +34,13 @@ func loadConfigFile(configFile string) (io.ReadCloser, error) {
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
content, err := buf.ReadAllToMultiBuffer(file)
|
content, err := buf.ReadFrom(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to load config file: ", fixedFile).Base(err).AtWarning()
|
return nil, newError("failed to load config file: ", fixedFile).Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
return &ClosableMultiBuffer{content}, nil
|
return &buf.MultiBufferContainer{
|
||||||
|
MultiBuffer: content,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/platform/ctlcmd"
|
"v2ray.com/core/common/platform/ctlcmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,7 +20,9 @@ func init() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning()
|
return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
return core.LoadConfig("protobuf", "", &jsonContent)
|
return core.LoadConfig("protobuf", "", &buf.MultiBufferContainer{
|
||||||
|
MultiBuffer: jsonContent,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,8 +185,7 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade
|
||||||
}
|
}
|
||||||
|
|
||||||
if reader.Buffered() > 0 {
|
if reader.Buffered() > 0 {
|
||||||
var payload buf.MultiBuffer
|
payload, err := buf.ReadFrom(io.LimitReader(reader, int64(reader.Buffered())))
|
||||||
_, err := payload.ReadFrom(&io.LimitedReader{R: reader, N: int64(reader.Buffered())})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,8 +92,7 @@ func (v *ChunkReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||||
return nil, newError("invalid auth")
|
return nil, newError("invalid auth")
|
||||||
}
|
}
|
||||||
|
|
||||||
var mb buf.MultiBuffer
|
mb := buf.MergeBytes(nil, payload)
|
||||||
common.Must2(mb.Write(payload))
|
|
||||||
|
|
||||||
return mb, nil
|
return mb, nil
|
||||||
}
|
}
|
||||||
|
@ -117,7 +116,7 @@ func (w *ChunkWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
defer buf.ReleaseMulti(mb)
|
defer buf.ReleaseMulti(mb)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
payloadLen, _ := mb.Read(w.buffer[2+AuthSize:])
|
mb, payloadLen, _ := buf.SplitBytes(mb, w.buffer[2+AuthSize:])
|
||||||
binary.BigEndian.PutUint16(w.buffer, uint16(payloadLen))
|
binary.BigEndian.PutUint16(w.buffer, uint16(payloadLen))
|
||||||
w.auth.Authenticate(w.buffer[2+AuthSize:2+AuthSize+payloadLen], w.buffer[2:])
|
w.auth.Authenticate(w.buffer[2+AuthSize:2+AuthSize+payloadLen], w.buffer[2:])
|
||||||
if err := buf.WriteAllBytes(w.writer, w.buffer[:2+AuthSize+payloadLen]); err != nil {
|
if err := buf.WriteAllBytes(w.writer, w.buffer[:2+AuthSize+payloadLen]); err != nil {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package kcp
|
package kcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -8,7 +9,6 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/signal"
|
"v2ray.com/core/common/signal"
|
||||||
"v2ray.com/core/common/signal/semaphore"
|
"v2ray.com/core/common/signal/semaphore"
|
||||||
|
@ -364,12 +364,8 @@ func (c *Connection) waitForDataOutput() error {
|
||||||
|
|
||||||
// Write implements io.Writer.
|
// Write implements io.Writer.
|
||||||
func (c *Connection) Write(b []byte) (int, error) {
|
func (c *Connection) Write(b []byte) (int, error) {
|
||||||
// This involves multiple copies of the buffer. But we don't expect this method to be used often.
|
reader := bytes.NewReader(b)
|
||||||
// Only wrapped connections such as TLS and WebSocket will call into this.
|
if err := c.writeMultiBufferInternal(reader); err != nil {
|
||||||
// TODO: improve efficiency.
|
|
||||||
var mb buf.MultiBuffer
|
|
||||||
common.Must2(mb.Write(b))
|
|
||||||
if err := c.WriteMultiBuffer(mb); err != nil {
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
|
@ -377,8 +373,15 @@ func (c *Connection) Write(b []byte) (int, error) {
|
||||||
|
|
||||||
// WriteMultiBuffer implements buf.Writer.
|
// WriteMultiBuffer implements buf.Writer.
|
||||||
func (c *Connection) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
func (c *Connection) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
defer buf.ReleaseMulti(mb)
|
reader := &buf.MultiBufferContainer{
|
||||||
|
MultiBuffer: mb,
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
|
return c.writeMultiBufferInternal(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) writeMultiBufferInternal(reader io.Reader) error {
|
||||||
updatePending := false
|
updatePending := false
|
||||||
defer func() {
|
defer func() {
|
||||||
if updatePending {
|
if updatePending {
|
||||||
|
@ -386,19 +389,28 @@ func (c *Connection) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
var b *buf.Buffer
|
||||||
|
defer b.Release()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
for {
|
for {
|
||||||
if c == nil || c.State() != StateActive {
|
if c == nil || c.State() != StateActive {
|
||||||
return io.ErrClosedPipe
|
return io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.sendingWorker.Push(&mb) {
|
if b == nil {
|
||||||
|
b = buf.New()
|
||||||
|
_, err := b.ReadFrom(io.LimitReader(reader, int64(c.mss)))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.sendingWorker.Push(b) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
updatePending = true
|
updatePending = true
|
||||||
if mb.IsEmpty() {
|
b = nil
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if updatePending {
|
if updatePending {
|
||||||
|
|
|
@ -209,7 +209,7 @@ func (w *ReceivingWorker) Read(b []byte) int {
|
||||||
if mb.IsEmpty() {
|
if mb.IsEmpty() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
nBytes, err := mb.Read(b)
|
mb, nBytes, err := buf.SplitBytes(mb, b)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if !mb.IsEmpty() {
|
if !mb.IsEmpty() {
|
||||||
w.leftOver = mb
|
w.leftOver = mb
|
||||||
|
|
|
@ -2,10 +2,8 @@ package kcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"io"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -262,7 +260,7 @@ func (w *SendingWorker) ProcessSegment(current uint32, seg *AckSegment, rto uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SendingWorker) Push(mb *buf.MultiBuffer) bool {
|
func (w *SendingWorker) Push(b *buf.Buffer) bool {
|
||||||
w.Lock()
|
w.Lock()
|
||||||
defer w.Unlock()
|
defer w.Unlock()
|
||||||
|
|
||||||
|
@ -274,8 +272,6 @@ func (w *SendingWorker) Push(mb *buf.MultiBuffer) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
b := buf.New()
|
|
||||||
common.Must2(b.ReadFrom(io.LimitReader(mb, int64(w.conn.mss))))
|
|
||||||
w.window.Push(w.nextNumber, b)
|
w.window.Push(w.nextNumber, b)
|
||||||
w.nextNumber++
|
w.nextNumber++
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in New Issue