From 20f046af0bac0b80bc6e49ec581e6a4ef6eca176 Mon Sep 17 00:00:00 2001 From: v2ray Date: Sat, 18 Jun 2016 17:01:48 +0200 Subject: [PATCH] fix a race condition issue in VMess inbound --- proxy/vmess/inbound/command.go | 3 +++ proxy/vmess/inbound/inbound.go | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/proxy/vmess/inbound/command.go b/proxy/vmess/inbound/command.go index 9e8a388c6..c4b7a14cd 100644 --- a/proxy/vmess/inbound/command.go +++ b/proxy/vmess/inbound/command.go @@ -18,6 +18,9 @@ func (this *VMessInboundHandler) generateCommand(request *protocol.RequestHeader log.Info("VMessIn: Pick detour handler for port ", inboundHandler.Port(), " for ", availableMin, " minutes.") user := inboundHandler.GetUser(request.User.Email) + if user == nil { + return nil + } return &protocol.CommandSwitchAccount{ Port: inboundHandler.Port(), ID: user.Account.(*protocol.VMessAccount).ID.UUID(), diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 43e46f898..d3c6334b5 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -65,7 +65,7 @@ func (this *userByEmail) Get(email string) (*protocol.User, bool) { // Inbound connection handler that handles messages in VMess format. type VMessInboundHandler struct { - sync.Mutex + sync.RWMutex packetDispatcher dispatcher.PacketDispatcher inboundHandlerManager proxyman.InboundHandlerManager clients protocol.UserValidator @@ -93,6 +93,13 @@ func (this *VMessInboundHandler) Close() { } func (this *VMessInboundHandler) GetUser(email string) *protocol.User { + this.RLock() + defer this.RUnlock() + + if !this.accepting { + return nil + } + user, existing := this.usersByEmail.Get(email) if !existing { this.clients.Add(user) @@ -120,16 +127,27 @@ func (this *VMessInboundHandler) Start() error { func (this *VMessInboundHandler) HandleConnection(connection internet.Connection) { defer connection.Close() + if !this.accepting { + return + } + connReader := v2net.NewTimeOutReader(8, connection) defer connReader.Release() reader := v2io.NewBufferedReader(connReader) defer reader.Release() + this.RLock() + if !this.accepting { + this.RUnlock() + return + } session := raw.NewServerSession(this.clients) defer session.Release() request, err := session.DecodeRequestHeader(reader) + this.RUnlock() + if err != nil { if err != io.EOF { log.Access(connection.RemoteAddr(), "", log.AccessRejected, err)