浏览代码

Remove log level detection during runtime

V2Ray 10 年之前
父节点
当前提交
efb881d73c
共有 7 个文件被更改,包括 123 次插入41 次删除
  1. 57 18
      common/log/log.go
  2. 19 0
      common/log/log_test.go
  3. 2 1
      proxy/freedom/freedom.go
  4. 11 9
      proxy/vmess/config.go
  5. 9 2
      proxy/vmess/protocol/user/id.go
  6. 6 3
      proxy/vmess/vmessin.go
  7. 19 8
      proxy/vmess/vmessout.go

+ 57 - 18
common/log/log.go

@@ -1,9 +1,9 @@
 package log
 
 import (
-	"errors"
 	"fmt"
-	"log"
+	"io"
+	"os"
 )
 
 const (
@@ -13,41 +13,80 @@ const (
 	ErrorLevel   = LogLevel(3)
 )
 
-var logLevel = WarningLevel
+type logger interface {
+	WriteLog(prefix, format string, v ...interface{})
+}
 
-type LogLevel int
+type noOpLogger struct {
+}
 
-func SetLogLevel(level LogLevel) {
-	logLevel = level
+func (l *noOpLogger) WriteLog(prefix, format string, v ...interface{}) {
+	// Swallow
 }
 
-func writeLog(level LogLevel, prefix, format string, v ...interface{}) string {
-	if level < logLevel {
-		return ""
-	}
+type streamLogger struct {
+	writer io.Writer
+}
+
+func (l *streamLogger) WriteLog(prefix, format string, v ...interface{}) {
 	var data string
 	if v == nil || len(v) == 0 {
 		data = format
 	} else {
 		data = fmt.Sprintf(format, v...)
 	}
-	log.Println(prefix + data)
-	return data
+	l.writer.Write([]byte(prefix + data))
+	l.writer.Write([]byte{'\n'})
+}
+
+var (
+	noOpLoggerInstance   logger = &noOpLogger{}
+	streamLoggerInstance logger = &streamLogger{
+		writer: os.Stdout,
+	}
+
+	debugLogger   = noOpLoggerInstance
+	infoLogger    = noOpLoggerInstance
+	warningLogger = noOpLoggerInstance
+	errorLogger   = noOpLoggerInstance
+)
+
+type LogLevel int
+
+func SetLogLevel(level LogLevel) {
+	debugLogger = noOpLoggerInstance
+	if level <= DebugLevel {
+		debugLogger = streamLoggerInstance
+	}
+
+	infoLogger = noOpLoggerInstance
+	if level <= InfoLevel {
+		infoLogger = streamLoggerInstance
+	}
+
+	warningLogger = noOpLoggerInstance
+	if level <= WarningLevel {
+		warningLogger = streamLoggerInstance
+	}
+
+	errorLogger = noOpLoggerInstance
+	if level <= ErrorLevel {
+		errorLogger = streamLoggerInstance
+	}
 }
 
 func Debug(format string, v ...interface{}) {
-	writeLog(DebugLevel, "[Debug]", format, v...)
+	debugLogger.WriteLog("[Debug]", format, v...)
 }
 
 func Info(format string, v ...interface{}) {
-	writeLog(InfoLevel, "[Info]", format, v...)
+	infoLogger.WriteLog("[Info]", format, v...)
 }
 
 func Warning(format string, v ...interface{}) {
-	writeLog(WarningLevel, "[Warning]", format, v...)
+	warningLogger.WriteLog("[Warning]", format, v...)
 }
 
-func Error(format string, v ...interface{}) error {
-	data := writeLog(ErrorLevel, "[Error]", format, v...)
-	return errors.New(data)
+func Error(format string, v ...interface{}) {
+	errorLogger.WriteLog("[Error]", format, v...)
 }

+ 19 - 0
common/log/log_test.go

@@ -0,0 +1,19 @@
+package log
+
+import (
+	"testing"
+
+	"github.com/v2ray/v2ray-core/testing/unit"
+)
+
+func TestLogLevelSetting(t *testing.T) {
+	assert := unit.Assert(t)
+
+	assert.Pointer(debugLogger).Equals(noOpLoggerInstance)
+	SetLogLevel(DebugLevel)
+	assert.Pointer(debugLogger).Equals(streamLoggerInstance)
+
+	SetLogLevel(InfoLevel)
+	assert.Pointer(debugLogger).Equals(noOpLoggerInstance)
+	assert.Pointer(infoLogger).Equals(streamLoggerInstance)
+}

+ 2 - 1
proxy/freedom/freedom.go

@@ -22,7 +22,8 @@ func (vconn *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray core.Outb
 	log.Info("Freedom: Opening connection to %s", firstPacket.Destination().String())
 	if err != nil {
 		close(ray.OutboundOutput())
-		return log.Error("Freedom: Failed to open connection: %s : %v", firstPacket.Destination().String(), err)
+		log.Error("Freedom: Failed to open connection: %s : %v", firstPacket.Destination().String(), err)
+		return err
 	}
 
 	input := ray.OutboundInput()

+ 11 - 9
proxy/vmess/config.go

@@ -41,30 +41,32 @@ func (config VNextConfig) HasNetwork(network string) bool {
 	return strings.Contains(config.Network, network)
 }
 
-func (config VNextConfig) ToVNextServer(network string) VNextServer {
-	users := make([]user.User, 0, len(config.Users))
-	for _, user := range config.Users {
+func (c VNextConfig) ToVNextServer(network string) (*VNextServer, error) {
+	users := make([]user.User, 0, len(c.Users))
+	for _, user := range c.Users {
 		vuser, err := user.ToUser()
 		if err != nil {
-			panic(log.Error("Failed to convert %v to User.", user))
+			log.Error("Failed to convert %v to User.", user)
+			return nil, config.BadConfiguration
 		}
 		users = append(users, vuser)
 	}
-	ip := net.ParseIP(config.Address)
+	ip := net.ParseIP(c.Address)
 	if ip == nil {
-		panic(log.Error("Unable to parse VNext IP: %s", config.Address))
+		log.Error("Unable to parse VNext IP: %s", c.Address)
+		return nil, config.BadConfiguration
 	}
-	address := v2net.IPAddress(ip, config.Port)
+	address := v2net.IPAddress(ip, c.Port)
 	var dest v2net.Destination
 	if network == "tcp" {
 		dest = v2net.NewTCPDestination(address)
 	} else {
 		dest = v2net.NewUDPDestination(address)
 	}
-	return VNextServer{
+	return &VNextServer{
 		Destination: dest,
 		Users:       users,
-	}
+	}, nil
 }
 
 type VMessOutboundConfig struct {

+ 9 - 2
proxy/vmess/protocol/user/id.go

@@ -3,6 +3,7 @@ package user
 import (
 	"crypto/md5"
 	"encoding/hex"
+	"errors"
 
 	"github.com/v2ray/v2ray-core/common/log"
 )
@@ -11,6 +12,10 @@ const (
 	IDBytesLen = 16
 )
 
+var (
+	InvalidID = errors.New("Invalid ID.")
+)
+
 // The ID of en entity, in the form of an UUID.
 type ID struct {
 	String string
@@ -21,7 +26,8 @@ type ID struct {
 func NewID(id string) (ID, error) {
 	idBytes, err := UUIDToID(id)
 	if err != nil {
-		return ID{}, log.Error("Failed to parse id %s", id)
+		log.Error("Failed to parse id %s", id)
+		return ID{}, InvalidID
 	}
 
 	md5hash := md5.New()
@@ -46,7 +52,8 @@ var byteGroups = []int{8, 4, 4, 4, 12}
 func UUIDToID(uuid string) (v [IDBytesLen]byte, err error) {
 	text := []byte(uuid)
 	if len(text) < 32 {
-		err = log.Error("uuid: invalid UUID string: %s", text)
+		log.Error("uuid: invalid UUID string: %s", text)
+		err = InvalidID
 		return
 	}
 

+ 6 - 3
proxy/vmess/vmessin.go

@@ -37,7 +37,8 @@ func (handler *VMessInboundHandler) Listen(port uint16) error {
 		Zone: "",
 	})
 	if err != nil {
-		return log.Error("Unable to listen tcp:%d", port)
+		log.Error("Unable to listen tcp port %d: %v", port, err)
+		return err
 	}
 	handler.accepting = true
 	go handler.AcceptConnections(listener)
@@ -90,7 +91,8 @@ func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) er
 
 	responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection)
 	if err != nil {
-		return log.Error("VMessIn: Failed to create encrypt writer: %v", err)
+		log.Error("VMessIn: Failed to create encrypt writer: %v", err)
+		return err
 	}
 
 	// Optimize for small response packet
@@ -140,7 +142,8 @@ func (factory *VMessInboundHandlerFactory) Create(vp *core.Point, rawConfig inte
 	for _, client := range config.AllowedClients {
 		user, err := client.ToUser()
 		if err != nil {
-			panic(log.Error("VMessIn: Failed to parse user id %s: %v", client.Id, err))
+			log.Error("VMessIn: Failed to parse user id %s: %v", client.Id, err)
+			return nil, err
 		}
 		allowedClients.AddUser(user)
 	}

+ 19 - 8
proxy/vmess/vmessout.go

@@ -29,11 +29,11 @@ type VNextServer struct {
 
 type VMessOutboundHandler struct {
 	vPoint       *core.Point
-	vNextList    []VNextServer
-	vNextListUDP []VNextServer
+	vNextList    []*VNextServer
+	vNextListUDP []*VNextServer
 }
 
-func NewVMessOutboundHandler(vp *core.Point, vNextList, vNextListUDP []VNextServer) *VMessOutboundHandler {
+func NewVMessOutboundHandler(vp *core.Point, vNextList, vNextListUDP []*VNextServer) *VMessOutboundHandler {
 	return &VMessOutboundHandler{
 		vPoint:       vp,
 		vNextList:    vNextList,
@@ -41,7 +41,7 @@ func NewVMessOutboundHandler(vp *core.Point, vNextList, vNextListUDP []VNextServ
 	}
 }
 
-func pickVNext(serverList []VNextServer) (v2net.Destination, user.User) {
+func pickVNext(serverList []*VNextServer) (v2net.Destination, user.User) {
 	vNextLen := len(serverList)
 	if vNextLen == 0 {
 		panic("VMessOut: Zero vNext is configured.")
@@ -201,14 +201,25 @@ type VMessOutboundHandlerFactory struct {
 
 func (factory *VMessOutboundHandlerFactory) Create(vp *core.Point, rawConfig interface{}) (core.OutboundConnectionHandler, error) {
 	config := rawConfig.(*VMessOutboundConfig)
-	servers := make([]VNextServer, 0, len(config.VNextList))
-	udpServers := make([]VNextServer, 0, len(config.VNextList))
+	servers := make([]*VNextServer, 0, len(config.VNextList))
+	udpServers := make([]*VNextServer, 0, len(config.VNextList))
 	for _, server := range config.VNextList {
 		if server.HasNetwork("tcp") {
-			servers = append(servers, server.ToVNextServer("tcp"))
+			aServer, err := server.ToVNextServer("tcp")
+			if err == nil {
+				servers = append(servers, aServer)
+			} else {
+				log.Warning("Discarding the server.")
+			}
 		}
 		if server.HasNetwork("udp") {
-			udpServers = append(udpServers, server.ToVNextServer("udp"))
+			aServer, err := server.ToVNextServer("udp")
+			if err == nil {
+				udpServers = append(udpServers, aServer)
+			} else {
+				log.Warning("Discarding the server.")
+			}
+
 		}
 	}
 	return NewVMessOutboundHandler(vp, servers, udpServers), nil