|
|
@@ -15,13 +15,75 @@ import (
|
|
|
v2net "v2ray.com/core/common/net"
|
|
|
"v2ray.com/core/common/protocol"
|
|
|
"v2ray.com/core/common/serial"
|
|
|
+ "v2ray.com/core/common/task"
|
|
|
"v2ray.com/core/common/uuid"
|
|
|
"v2ray.com/core/proxy"
|
|
|
"v2ray.com/core/proxy/vmess"
|
|
|
"v2ray.com/core/proxy/vmess/encoding"
|
|
|
"v2ray.com/core/transport/internet"
|
|
|
+ "v2ray.com/core/transport/ray"
|
|
|
)
|
|
|
|
|
|
+type requestProcessor struct {
|
|
|
+ session *encoding.ServerSession
|
|
|
+ request *protocol.RequestHeader
|
|
|
+ input io.Reader
|
|
|
+ output ray.OutputStream
|
|
|
+}
|
|
|
+
|
|
|
+func (r *requestProcessor) Execute() error {
|
|
|
+ defer r.output.Close()
|
|
|
+
|
|
|
+ bodyReader := r.session.DecodeRequestBody(r.request, r.input)
|
|
|
+ defer bodyReader.Release()
|
|
|
+
|
|
|
+ if err := buf.PipeUntilEOF(bodyReader, r.output); err != nil {
|
|
|
+ log.Debug("VMess|Inbound: Error when sending data to outbound: ", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+type responseProcessor struct {
|
|
|
+ session *encoding.ServerSession
|
|
|
+ request *protocol.RequestHeader
|
|
|
+ response *protocol.ResponseHeader
|
|
|
+ input ray.InputStream
|
|
|
+ output io.Writer
|
|
|
+}
|
|
|
+
|
|
|
+func (r *responseProcessor) Execute() error {
|
|
|
+ defer r.input.Release()
|
|
|
+ r.session.EncodeResponseHeader(r.response, r.output)
|
|
|
+
|
|
|
+ bodyWriter := r.session.EncodeResponseBody(r.request, r.output)
|
|
|
+
|
|
|
+ // Optimize for small response packet
|
|
|
+ if data, err := r.input.Read(); err == nil {
|
|
|
+ if err := bodyWriter.Write(data); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ if bufferedWriter, ok := r.output.(*bufio.BufferedWriter); ok {
|
|
|
+ bufferedWriter.SetBuffered(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := buf.PipeUntilEOF(r.input, bodyWriter); err != nil {
|
|
|
+ log.Debug("VMess|Inbound: Error when sending data to downstream: ", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if r.request.Option.Has(protocol.RequestOptionChunkStream) {
|
|
|
+ if err := bodyWriter.Write(buf.NewLocal(8)); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
type userByEmail struct {
|
|
|
sync.RWMutex
|
|
|
cache map[string]*protocol.User
|
|
|
@@ -176,24 +238,17 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
|
|
|
defer input.Close()
|
|
|
defer output.Release()
|
|
|
|
|
|
- var readFinish sync.Mutex
|
|
|
- readFinish.Lock()
|
|
|
-
|
|
|
userSettings := request.User.GetSettings()
|
|
|
connReader.SetTimeOut(userSettings.PayloadReadTimeout)
|
|
|
reader.SetBuffered(false)
|
|
|
|
|
|
- go func() {
|
|
|
- bodyReader := session.DecodeRequestBody(request, reader)
|
|
|
- if err := buf.PipeUntilEOF(bodyReader, input); err != nil {
|
|
|
- log.Debug("VMess|Inbound: Error when sending data to outbound: ", err)
|
|
|
- connection.SetReusable(false)
|
|
|
- }
|
|
|
- bodyReader.Release()
|
|
|
-
|
|
|
- input.Close()
|
|
|
- readFinish.Unlock()
|
|
|
- }()
|
|
|
+ var executor task.ParallelExecutor
|
|
|
+ executor.Execute(&requestProcessor{
|
|
|
+ session: session,
|
|
|
+ request: request,
|
|
|
+ input: reader,
|
|
|
+ output: input,
|
|
|
+ })
|
|
|
|
|
|
writer := bufio.NewWriter(connection)
|
|
|
defer writer.Release()
|
|
|
@@ -206,34 +261,24 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
|
|
|
response.Option.Set(protocol.ResponseOptionConnectionReuse)
|
|
|
}
|
|
|
|
|
|
- session.EncodeResponseHeader(response, writer)
|
|
|
-
|
|
|
- bodyWriter := session.EncodeResponseBody(request, writer)
|
|
|
-
|
|
|
- // Optimize for small response packet
|
|
|
- if data, err := output.Read(); err == nil {
|
|
|
- if err := bodyWriter.Write(data); err != nil {
|
|
|
- connection.SetReusable(false)
|
|
|
- }
|
|
|
-
|
|
|
- writer.SetBuffered(false)
|
|
|
+ executor.Execute(&responseProcessor{
|
|
|
+ session: session,
|
|
|
+ request: request,
|
|
|
+ response: response,
|
|
|
+ input: output,
|
|
|
+ output: writer,
|
|
|
+ })
|
|
|
|
|
|
- if err := buf.PipeUntilEOF(output, bodyWriter); err != nil {
|
|
|
- log.Debug("VMess|Inbound: Error when sending data to downstream: ", err)
|
|
|
- connection.SetReusable(false)
|
|
|
- }
|
|
|
+ executor.Wait()
|
|
|
|
|
|
+ if err := writer.Flush(); err != nil {
|
|
|
+ connection.SetReusable(false)
|
|
|
}
|
|
|
- output.Release()
|
|
|
- if request.Option.Has(protocol.RequestOptionChunkStream) {
|
|
|
- if err := bodyWriter.Write(buf.NewLocal(8)); err != nil {
|
|
|
- connection.SetReusable(false)
|
|
|
- }
|
|
|
- }
|
|
|
- writer.Flush()
|
|
|
- bodyWriter.Release()
|
|
|
|
|
|
- readFinish.Lock()
|
|
|
+ errors := executor.Errors()
|
|
|
+ if len(errors) > 0 {
|
|
|
+ connection.SetReusable(false)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
type Factory struct{}
|