mirror of https://github.com/v2ray/v2ray-core
optimize http server
parent
54b441d690
commit
8868fe68ed
|
@ -1,6 +1,10 @@
|
||||||
package buf
|
package buf
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"v2ray.com/core/common/errors"
|
||||||
|
)
|
||||||
|
|
||||||
// BytesToBufferReader is a Reader that adjusts its reading speed automatically.
|
// BytesToBufferReader is a Reader that adjusts its reading speed automatically.
|
||||||
type BytesToBufferReader struct {
|
type BytesToBufferReader struct {
|
||||||
|
@ -9,20 +13,40 @@ type BytesToBufferReader struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read implements Reader.Read().
|
// Read implements Reader.Read().
|
||||||
func (v *BytesToBufferReader) Read() (MultiBuffer, error) {
|
func (r *BytesToBufferReader) Read() (MultiBuffer, error) {
|
||||||
if err := v.buffer.Reset(ReadFrom(v.reader)); err != nil {
|
if err := r.buffer.Reset(ReadFrom(r.reader)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mb := NewMultiBuffer()
|
mb := NewMultiBuffer()
|
||||||
for !v.buffer.IsEmpty() {
|
for !r.buffer.IsEmpty() {
|
||||||
b := New()
|
b := New()
|
||||||
b.AppendSupplier(ReadFrom(v.buffer))
|
b.AppendSupplier(ReadFrom(r.buffer))
|
||||||
mb.Append(b)
|
mb.Append(b)
|
||||||
}
|
}
|
||||||
return mb, nil
|
return mb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *BytesToBufferReader) WriteTo(writer io.Writer) (int64, error) {
|
||||||
|
totalBytes := int64(0)
|
||||||
|
eof := false
|
||||||
|
for !eof {
|
||||||
|
if err := r.buffer.Reset(ReadFrom(r.reader)); err != nil {
|
||||||
|
if errors.Cause(err) == io.EOF {
|
||||||
|
eof = true
|
||||||
|
} else {
|
||||||
|
return totalBytes, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nBytes, err := writer.Write(r.buffer.Bytes())
|
||||||
|
totalBytes += int64(nBytes)
|
||||||
|
if err != nil {
|
||||||
|
return totalBytes, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
type readerAdpater struct {
|
type readerAdpater struct {
|
||||||
MultiBufferReader
|
MultiBufferReader
|
||||||
}
|
}
|
||||||
|
@ -38,45 +62,75 @@ type bufferToBytesReader struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill fills in the internal buffer.
|
// fill fills in the internal buffer.
|
||||||
func (v *bufferToBytesReader) fill() {
|
func (r *bufferToBytesReader) fill() {
|
||||||
b, err := v.stream.Read()
|
b, err := r.stream.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.err = err
|
r.err = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v.current = b
|
r.current = b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *bufferToBytesReader) Read(b []byte) (int, error) {
|
func (r *bufferToBytesReader) Read(b []byte) (int, error) {
|
||||||
if v.err != nil {
|
if r.err != nil {
|
||||||
return 0, v.err
|
return 0, r.err
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.current == nil {
|
if r.current == nil {
|
||||||
v.fill()
|
r.fill()
|
||||||
if v.err != nil {
|
if r.err != nil {
|
||||||
return 0, v.err
|
return 0, r.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nBytes, err := v.current.Read(b)
|
nBytes, err := r.current.Read(b)
|
||||||
if v.current.IsEmpty() {
|
if r.current.IsEmpty() {
|
||||||
v.current.Release()
|
r.current.Release()
|
||||||
v.current = nil
|
r.current = nil
|
||||||
}
|
}
|
||||||
return nBytes, err
|
return nBytes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *bufferToBytesReader) ReadMultiBuffer() (MultiBuffer, error) {
|
func (r *bufferToBytesReader) ReadMultiBuffer() (MultiBuffer, error) {
|
||||||
if v.err != nil {
|
if r.err != nil {
|
||||||
return nil, v.err
|
return nil, r.err
|
||||||
}
|
}
|
||||||
if v.current == nil {
|
if r.current == nil {
|
||||||
v.fill()
|
r.fill()
|
||||||
if v.err != nil {
|
if r.err != nil {
|
||||||
return nil, v.err
|
return nil, r.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b := v.current
|
b := r.current
|
||||||
v.current = nil
|
r.current = nil
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *bufferToBytesReader) writeToInternal(writer io.Writer) (int64, error) {
|
||||||
|
if r.err != nil {
|
||||||
|
return 0, r.err
|
||||||
|
}
|
||||||
|
|
||||||
|
mbWriter := NewWriter(writer)
|
||||||
|
totalBytes := int64(0)
|
||||||
|
for {
|
||||||
|
if r.current == nil {
|
||||||
|
r.fill()
|
||||||
|
if r.err != nil {
|
||||||
|
return totalBytes, r.err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalBytes := int64(r.current.Len())
|
||||||
|
if err := mbWriter.Write(r.current); err != nil {
|
||||||
|
return totalBytes, err
|
||||||
|
}
|
||||||
|
r.current = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *bufferToBytesReader) WriteTo(writer io.Writer) (int64, error) {
|
||||||
|
nBytes, err := r.writeToInternal(writer)
|
||||||
|
if errors.Cause(err) == io.EOF {
|
||||||
|
return nBytes, nil
|
||||||
|
}
|
||||||
|
return nBytes, err
|
||||||
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ type BufferToBytesWriter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write implements Writer.Write(). Write() takes ownership of the given buffer.
|
// Write implements Writer.Write(). Write() takes ownership of the given buffer.
|
||||||
func (v *BufferToBytesWriter) Write(mb MultiBuffer) error {
|
func (w *BufferToBytesWriter) Write(mb MultiBuffer) error {
|
||||||
if mw, ok := v.writer.(MultiBufferWriter); ok {
|
if mw, ok := w.writer.(MultiBufferWriter); ok {
|
||||||
_, err := mw.WriteMultiBuffer(mb)
|
_, err := mw.WriteMultiBuffer(mb)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ func (v *BufferToBytesWriter) Write(mb MultiBuffer) error {
|
||||||
defer mb.Release()
|
defer mb.Release()
|
||||||
|
|
||||||
bs := mb.ToNetBuffers()
|
bs := mb.ToNetBuffers()
|
||||||
_, err := bs.WriteTo(v.writer)
|
_, err := bs.WriteTo(w.writer)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,3 +42,22 @@ func (w *bytesToBufferWriter) Write(payload []byte) (int, error) {
|
||||||
func (w *bytesToBufferWriter) WriteMulteBuffer(mb MultiBuffer) (int, error) {
|
func (w *bytesToBufferWriter) WriteMulteBuffer(mb MultiBuffer) (int, error) {
|
||||||
return mb.Len(), w.writer.Write(mb)
|
return mb.Len(), w.writer.Write(mb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *bytesToBufferWriter) ReadFrom(reader io.Reader) (int64, error) {
|
||||||
|
mbReader := NewReader(reader)
|
||||||
|
totalBytes := int64(0)
|
||||||
|
eof := false
|
||||||
|
for !eof {
|
||||||
|
mb, err := mbReader.Read()
|
||||||
|
if err == io.EOF {
|
||||||
|
eof = true
|
||||||
|
} else if err != nil {
|
||||||
|
return totalBytes, err
|
||||||
|
}
|
||||||
|
totalBytes += int64(mb.Len())
|
||||||
|
if err := w.writer.Write(mb); err != nil {
|
||||||
|
return totalBytes, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalBytes, nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
package buf_test
|
package buf_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
. "v2ray.com/core/common/buf"
|
. "v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
|
"v2ray.com/core/transport/ray"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWriter(t *testing.T) {
|
func TestWriter(t *testing.T) {
|
||||||
|
@ -24,3 +29,17 @@ func TestWriter(t *testing.T) {
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
assert.Bytes(expectedBytes).Equals(writeBuffer.Bytes())
|
assert.Bytes(expectedBytes).Equals(writeBuffer.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBytesWriterReadFrom(t *testing.T) {
|
||||||
|
assert := assert.On(t)
|
||||||
|
|
||||||
|
cache := ray.NewStream(context.Background())
|
||||||
|
reader := bufio.NewReader(io.LimitReader(rand.Reader, 8192))
|
||||||
|
_, err := reader.WriteTo(ToBytesWriter(cache))
|
||||||
|
assert.Error(err).IsNil()
|
||||||
|
|
||||||
|
mb, err := cache.Read()
|
||||||
|
assert.Error(err).IsNil()
|
||||||
|
assert.Int(mb.Len()).Equals(8192)
|
||||||
|
assert.Int(len(mb)).Equals(4)
|
||||||
|
}
|
||||||
|
|
|
@ -235,12 +235,8 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea
|
||||||
requestDone := signal.ExecuteAsync(func() error {
|
requestDone := signal.ExecuteAsync(func() error {
|
||||||
request.Header.Set("Connection", "close")
|
request.Header.Set("Connection", "close")
|
||||||
|
|
||||||
requestWriter := buf.NewBufferedWriter(buf.ToBytesWriter(ray.InboundInput()))
|
requestWriter := buf.ToBytesWriter(ray.InboundInput())
|
||||||
err := request.Write(requestWriter)
|
if err := request.Write(requestWriter); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := requestWriter.Flush(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -271,12 +267,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea
|
||||||
response.Header.Set("Connection", "close")
|
response.Header.Set("Connection", "close")
|
||||||
response.Header.Set("Proxy-Connection", "close")
|
response.Header.Set("Proxy-Connection", "close")
|
||||||
}
|
}
|
||||||
responseWriter := buf.NewBufferedWriter(writer)
|
if err := response.Write(writer); err != nil {
|
||||||
if err := response.Write(responseWriter); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := responseWriter.Flush(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue