able to close ray stream with error

pull/362/head
Darien Raymond 2017-01-10 14:22:42 +01:00
parent 1cf9cd5d78
commit 72992c7478
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
15 changed files with 57 additions and 61 deletions

View File

@ -71,7 +71,7 @@ func (v *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.I
func (v *DefaultDispatcher) waitAndDispatch(wait func() error, destination v2net.Destination, link ray.OutboundRay, dispatcher proxy.OutboundHandler) { func (v *DefaultDispatcher) waitAndDispatch(wait func() error, destination v2net.Destination, link ray.OutboundRay, dispatcher proxy.OutboundHandler) {
if err := wait(); err != nil { if err := wait(); err != nil {
log.Info("DefaultDispatcher: Failed precondition: ", err) log.Info("DefaultDispatcher: Failed precondition: ", err)
link.OutboundInput().ForceClose() link.OutboundInput().CloseError()
link.OutboundOutput().Close() link.OutboundOutput().Close()
return return
} }

View File

@ -98,7 +98,7 @@ func (v *Connection) Write(b []byte) (int, error) {
func (v *Connection) Close() error { func (v *Connection) Close() error {
v.closed = true v.closed = true
v.stream.InboundInput().Close() v.stream.InboundInput().Close()
v.stream.InboundOutput().ForceClose() v.stream.InboundOutput().CloseError()
return nil return nil
} }

View File

@ -31,7 +31,7 @@ func (v *Handler) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
v.response.WriteTo(ray.OutboundOutput()) v.response.WriteTo(ray.OutboundOutput())
ray.OutboundOutput().Close() ray.OutboundOutput().Close()
ray.OutboundInput().ForceClose() ray.OutboundInput().CloseError()
} }
// Factory is an utility for creating blackhole handlers. // Factory is an utility for creating blackhole handlers.

View File

@ -172,8 +172,6 @@ func (v *DokodemoDoor) HandleTCPConnection(conn internet.Connection) {
Destination: dest, Destination: dest,
Inbound: v.meta, Inbound: v.meta,
}) })
output := ray.InboundOutput()
defer output.ForceClose()
reader := v2net.NewTimeOutReader(v.config.Timeout, conn) reader := v2net.NewTimeOutReader(v.config.Timeout, conn)
@ -191,11 +189,9 @@ func (v *DokodemoDoor) HandleTCPConnection(conn internet.Connection) {
}) })
responseDone := signal.ExecuteAsync(func() error { responseDone := signal.ExecuteAsync(func() error {
defer output.ForceClose()
v2writer := buf.NewWriter(conn) v2writer := buf.NewWriter(conn)
if err := buf.PipeUntilEOF(output, 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)
return err return err
} }
@ -203,6 +199,8 @@ func (v *DokodemoDoor) HandleTCPConnection(conn internet.Connection) {
}) })
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
ray.InboundInput().CloseError()
ray.InboundOutput().CloseError()
log.Info("Dokodemo: Connection ends with ", err) log.Info("Dokodemo: Connection ends with ", err)
} }
} }

View File

@ -72,8 +72,6 @@ func (v *Handler) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
input := ray.OutboundInput() input := ray.OutboundInput()
output := ray.OutboundOutput() output := ray.OutboundOutput()
defer input.ForceClose()
defer output.Close()
var conn internet.Connection var conn internet.Connection
if v.domainStrategy == Config_USE_IP && destination.Address.Family().IsDomain() { if v.domainStrategy == Config_USE_IP && destination.Address.Family().IsDomain() {
@ -96,8 +94,6 @@ func (v *Handler) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
conn.SetReusable(false) conn.SetReusable(false)
requestDone := signal.ExecuteAsync(func() error { requestDone := signal.ExecuteAsync(func() error {
defer input.ForceClose()
v2writer := buf.NewWriter(conn) v2writer := buf.NewWriter(conn)
if err := buf.PipeUntilEOF(input, v2writer); err != nil { if err := buf.PipeUntilEOF(input, v2writer); err != nil {
return err return err
@ -127,6 +123,8 @@ func (v *Handler) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("Freedom: Connection ending with ", err) log.Info("Freedom: Connection ending with ", err)
input.CloseError()
output.CloseError()
} }
} }

View File

@ -176,8 +176,6 @@ func (v *Server) handleConnect(request *http.Request, session *proxy.SessionInfo
}) })
responseDone := signal.ExecuteAsync(func() error { responseDone := signal.ExecuteAsync(func() error {
defer ray.InboundOutput().ForceClose()
v2writer := buf.NewWriter(writer) v2writer := buf.NewWriter(writer)
if err := buf.PipeUntilEOF(ray.InboundOutput(), v2writer); err != nil { if err := buf.PipeUntilEOF(ray.InboundOutput(), v2writer); err != nil {
return err return err
@ -185,7 +183,11 @@ func (v *Server) handleConnect(request *http.Request, session *proxy.SessionInfo
return nil return nil
}) })
signal.ErrorOrFinish2(requestDone, responseDone) if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("HTTP|Server: Connection ends with: ", err)
ray.InboundInput().CloseError()
ray.InboundOutput().CloseError()
}
} }
// @VisibleForTesting // @VisibleForTesting
@ -244,9 +246,6 @@ func (v *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionIn
input := ray.InboundInput() input := ray.InboundInput()
output := ray.InboundOutput() output := ray.InboundOutput()
defer input.Close()
defer output.ForceClose()
requestDone := signal.ExecuteAsync(func() error { requestDone := signal.ExecuteAsync(func() error {
defer input.Close() defer input.Close()
@ -262,8 +261,6 @@ func (v *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionIn
}) })
responseDone := signal.ExecuteAsync(func() error { responseDone := signal.ExecuteAsync(func() error {
defer output.ForceClose()
responseReader := bufio.OriginalReader(buf.NewBytesReader(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 {
@ -283,6 +280,8 @@ func (v *Server) handlePlainHTTP(request *http.Request, session *proxy.SessionIn
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("HTTP|Server: Connecton ending with ", err) log.Info("HTTP|Server: Connecton ending with ", err)
input.CloseError()
output.CloseError()
} }
} }

View File

@ -96,8 +96,6 @@ func (v *Client) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
bufferedWriter.SetBuffered(false) bufferedWriter.SetBuffered(false)
requestDone := signal.ExecuteAsync(func() error { requestDone := signal.ExecuteAsync(func() error {
defer ray.OutboundInput().ForceClose()
if err := buf.PipeUntilEOF(ray.OutboundInput(), bodyWriter); err != nil { if err := buf.PipeUntilEOF(ray.OutboundInput(), bodyWriter); err != nil {
return err return err
} }
@ -121,6 +119,8 @@ func (v *Client) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("Shadowsocks|Client: Connection ends with ", err) log.Info("Shadowsocks|Client: Connection ends with ", err)
ray.OutboundInput().CloseError()
ray.OutboundOutput().CloseError()
} }
} }
@ -132,8 +132,6 @@ func (v *Client) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
} }
requestDone := signal.ExecuteAsync(func() error { requestDone := signal.ExecuteAsync(func() error {
defer ray.OutboundInput().ForceClose()
if err := buf.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)
return err return err
@ -158,7 +156,11 @@ func (v *Client) Dispatch(destination v2net.Destination, ray ray.OutboundRay) {
return nil return nil
}) })
signal.ErrorOrFinish2(requestDone, responseDone) if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("Shadowsocks|Client: Connection ends with ", err)
ray.OutboundInput().CloseError()
ray.OutboundOutput().CloseError()
}
} }
} }

View File

@ -169,12 +169,8 @@ func (v *Server) handleConnection(conn internet.Connection) {
User: request.User, User: request.User,
Inbound: v.meta, Inbound: v.meta,
}) })
defer ray.InboundOutput().ForceClose()
defer ray.InboundInput().Close()
requestDone := signal.ExecuteAsync(func() error { requestDone := signal.ExecuteAsync(func() error {
defer ray.InboundOutput().ForceClose()
bufferedWriter := bufio.NewWriter(conn) bufferedWriter := bufio.NewWriter(conn)
responseWriter, err := WriteTCPResponse(request, bufferedWriter) responseWriter, err := WriteTCPResponse(request, bufferedWriter)
if err != nil { if err != nil {
@ -215,6 +211,8 @@ func (v *Server) handleConnection(conn internet.Connection) {
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("Shadowsocks|Server: Connection ends with ", err) log.Info("Shadowsocks|Server: Connection ends with ", err)
ray.InboundInput().CloseError()
ray.InboundOutput().CloseError()
} }
} }

View File

@ -80,7 +80,6 @@ func (c *Client) Dispatch(destination net.Destination, ray ray.OutboundRay) {
var responseFunc func() error var responseFunc func() error
if request.Command == protocol.RequestCommandTCP { if request.Command == protocol.RequestCommandTCP {
requestFunc = func() error { requestFunc = func() error {
defer ray.OutboundInput().ForceClose()
return buf.PipeUntilEOF(ray.OutboundInput(), buf.NewWriter(conn)) return buf.PipeUntilEOF(ray.OutboundInput(), buf.NewWriter(conn))
} }
responseFunc = func() error { responseFunc = func() error {
@ -95,7 +94,6 @@ func (c *Client) Dispatch(destination net.Destination, ray ray.OutboundRay) {
} }
defer udpConn.Close() defer udpConn.Close()
requestFunc = func() error { requestFunc = func() error {
defer ray.OutboundInput().ForceClose()
return buf.PipeUntilEOF(ray.OutboundInput(), &UDPWriter{request: request, writer: udpConn}) return buf.PipeUntilEOF(ray.OutboundInput(), &UDPWriter{request: request, writer: udpConn})
} }
responseFunc = func() error { responseFunc = func() error {
@ -109,6 +107,8 @@ func (c *Client) Dispatch(destination net.Destination, ray ray.OutboundRay) {
responseDone := signal.ExecuteAsync(responseFunc) responseDone := signal.ExecuteAsync(responseFunc)
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("Socks|Client: Connection ends with ", err) log.Info("Socks|Client: Connection ends with ", err)
ray.OutboundInput().CloseError()
ray.OutboundOutput().CloseError()
} }
} }

View File

@ -165,8 +165,6 @@ func (v *Server) transport(reader io.Reader, writer io.Writer, session *proxy.Se
}) })
responseDone := signal.ExecuteAsync(func() error { responseDone := signal.ExecuteAsync(func() error {
defer output.ForceClose()
v2writer := buf.NewWriter(writer) v2writer := buf.NewWriter(writer)
if err := buf.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)
@ -178,6 +176,8 @@ func (v *Server) transport(reader io.Reader, writer io.Writer, session *proxy.Se
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("Socks|Server: Connection ends with ", err) log.Info("Socks|Server: Connection ends with ", err)
input.CloseError()
output.CloseError()
} }
} }

View File

@ -141,7 +141,6 @@ func transferRequest(session *encoding.ServerSession, request *protocol.RequestH
} }
func transferResponse(session *encoding.ServerSession, request *protocol.RequestHeader, response *protocol.ResponseHeader, input ray.InputStream, output io.Writer) error { func transferResponse(session *encoding.ServerSession, request *protocol.RequestHeader, response *protocol.ResponseHeader, input ray.InputStream, output io.Writer) error {
defer input.ForceClose()
session.EncodeResponseHeader(response, output) session.EncodeResponseHeader(response, output)
bodyWriter := session.EncodeResponseBody(request, output) bodyWriter := session.EncodeResponseBody(request, output)
@ -215,8 +214,6 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
}) })
input := ray.InboundInput() input := ray.InboundInput()
output := ray.InboundOutput() output := ray.InboundOutput()
defer input.Close()
defer output.ForceClose()
userSettings := request.User.GetSettings() userSettings := request.User.GetSettings()
connReader.SetTimeOut(userSettings.PayloadReadTimeout) connReader.SetTimeOut(userSettings.PayloadReadTimeout)
@ -242,6 +239,8 @@ func (v *VMessInboundHandler) HandleConnection(connection internet.Connection) {
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("VMess|Inbound: Connection ending with ", err) log.Info("VMess|Inbound: Connection ending with ", err)
connection.SetReusable(false) connection.SetReusable(false)
input.CloseError()
output.CloseError()
return return
} }

View File

@ -30,9 +30,6 @@ type VMessOutboundHandler struct {
// Dispatch implements OutboundHandler.Dispatch(). // Dispatch implements OutboundHandler.Dispatch().
func (v *VMessOutboundHandler) Dispatch(target v2net.Destination, outboundRay ray.OutboundRay) { func (v *VMessOutboundHandler) Dispatch(target v2net.Destination, outboundRay ray.OutboundRay) {
defer outboundRay.OutboundInput().ForceClose()
defer outboundRay.OutboundOutput().Close()
var rec *protocol.ServerSpec var rec *protocol.ServerSpec
var conn internet.Connection var conn internet.Connection
@ -85,8 +82,6 @@ func (v *VMessOutboundHandler) Dispatch(target v2net.Destination, outboundRay ra
session := encoding.NewClientSession(protocol.DefaultIDHash) session := encoding.NewClientSession(protocol.DefaultIDHash)
requestDone := signal.ExecuteAsync(func() error { requestDone := signal.ExecuteAsync(func() error {
defer input.ForceClose()
writer := bufio.NewWriter(conn) writer := bufio.NewWriter(conn)
session.EncodeRequestHeader(request, writer) session.EncodeRequestHeader(request, writer)
@ -140,6 +135,8 @@ func (v *VMessOutboundHandler) Dispatch(target v2net.Destination, outboundRay ra
if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
log.Info("VMess|Outbound: Connection ending with ", err) log.Info("VMess|Outbound: Connection ending with ", err)
conn.SetReusable(false) conn.SetReusable(false)
input.CloseError()
output.CloseError()
} }
return return

View File

@ -88,7 +88,7 @@ func (v *TimedInboundRay) Release() {
} }
v.server = nil v.server = nil
v.inboundRay.InboundInput().Close() v.inboundRay.InboundInput().Close()
v.inboundRay.InboundOutput().ForceClose() v.inboundRay.InboundOutput().CloseError()
v.inboundRay = nil v.inboundRay = nil
} }

View File

@ -54,23 +54,23 @@ func (v *directRay) AddInspector(inspector Inspector) {
type Stream struct { type Stream struct {
buffer chan *buf.Buffer buffer chan *buf.Buffer
srcClose chan bool close chan bool
destClose chan bool err chan bool
inspector *InspectorChain inspector *InspectorChain
} }
func NewStream() *Stream { func NewStream() *Stream {
return &Stream{ return &Stream{
buffer: make(chan *buf.Buffer, bufferSize), buffer: make(chan *buf.Buffer, bufferSize),
srcClose: make(chan bool), close: make(chan bool),
destClose: make(chan bool), err: make(chan bool),
inspector: &InspectorChain{}, inspector: &InspectorChain{},
} }
} }
func (v *Stream) Read() (*buf.Buffer, error) { func (v *Stream) Read() (*buf.Buffer, error) {
select { select {
case <-v.destClose: case <-v.err:
return nil, io.ErrClosedPipe return nil, io.ErrClosedPipe
case b := <-v.buffer: case b := <-v.buffer:
return b, nil return b, nil
@ -78,9 +78,9 @@ func (v *Stream) Read() (*buf.Buffer, error) {
select { select {
case b := <-v.buffer: case b := <-v.buffer:
return b, nil return b, nil
case <-v.srcClose: case <-v.close:
return nil, io.EOF return nil, io.EOF
case <-v.destClose: case <-v.err:
return nil, io.ErrClosedPipe return nil, io.ErrClosedPipe
} }
} }
@ -88,7 +88,7 @@ func (v *Stream) Read() (*buf.Buffer, error) {
func (v *Stream) ReadTimeout(timeout time.Duration) (*buf.Buffer, error) { func (v *Stream) ReadTimeout(timeout time.Duration) (*buf.Buffer, error) {
select { select {
case <-v.destClose: case <-v.err:
return nil, io.ErrClosedPipe return nil, io.ErrClosedPipe
case b := <-v.buffer: case b := <-v.buffer:
return b, nil return b, nil
@ -96,9 +96,9 @@ func (v *Stream) ReadTimeout(timeout time.Duration) (*buf.Buffer, error) {
select { select {
case b := <-v.buffer: case b := <-v.buffer:
return b, nil return b, nil
case <-v.srcClose: case <-v.close:
return nil, io.EOF return nil, io.EOF
case <-v.destClose: case <-v.err:
return nil, io.ErrClosedPipe return nil, io.ErrClosedPipe
case <-time.After(timeout): case <-time.After(timeout):
return nil, ErrReadTimeout return nil, ErrReadTimeout
@ -112,15 +112,15 @@ func (v *Stream) Write(data *buf.Buffer) (err error) {
} }
select { select {
case <-v.destClose: case <-v.err:
return io.ErrClosedPipe return io.ErrClosedPipe
case <-v.srcClose: case <-v.close:
return io.ErrClosedPipe return io.ErrClosedPipe
default: default:
select { select {
case <-v.destClose: case <-v.err:
return io.ErrClosedPipe return io.ErrClosedPipe
case <-v.srcClose: case <-v.close:
return io.ErrClosedPipe return io.ErrClosedPipe
case v.buffer <- data: case v.buffer <- data:
v.inspector.Input(data) v.inspector.Input(data)
@ -132,13 +132,13 @@ func (v *Stream) Write(data *buf.Buffer) (err error) {
func (v *Stream) Close() { func (v *Stream) Close() {
defer swallowPanic() defer swallowPanic()
close(v.srcClose) close(v.close)
} }
func (v *Stream) ForceClose() { func (v *Stream) CloseError() {
defer swallowPanic() defer swallowPanic()
close(v.destClose) close(v.err)
v.Close() v.Close()
n := len(v.buffer) n := len(v.buffer)

View File

@ -35,13 +35,18 @@ type Ray interface {
AddInspector(Inspector) AddInspector(Inspector)
} }
type RayStream interface {
Close()
CloseError()
}
type InputStream interface { type InputStream interface {
buf.Reader buf.Reader
RayStream
ReadTimeout(time.Duration) (*buf.Buffer, error) ReadTimeout(time.Duration) (*buf.Buffer, error)
ForceClose()
} }
type OutputStream interface { type OutputStream interface {
buf.Writer buf.Writer
Close() RayStream
} }