Преглед изворни кода

Use smaller temporary buffers for port forward relaying to
reduce overall memory footprint.

Rod Hynes пре 9 година
родитељ
комит
ebcb5b8414
2 измењених фајлова са 25 додато и 20 уклоњено
  1. 18 17
      psiphon/server/config.go
  2. 7 3
      psiphon/server/tunnelServer.go

+ 18 - 17
psiphon/server/config.go

@@ -39,23 +39,24 @@ import (
 )
 )
 
 
 const (
 const (
-	SERVER_CONFIG_FILENAME            = "psiphon-server.config"
-	SERVER_ENTRY_FILENAME             = "serverEntry.dat"
-	DEFAULT_SERVER_IP_ADDRESS         = "127.0.0.1"
-	WEB_SERVER_SECRET_BYTE_LENGTH     = 32
-	DISCOVERY_VALUE_KEY_BYTE_LENGTH   = 32
-	WEB_SERVER_READ_TIMEOUT           = 10 * time.Second
-	WEB_SERVER_WRITE_TIMEOUT          = 10 * time.Second
-	SSH_USERNAME_SUFFIX_BYTE_LENGTH   = 8
-	SSH_PASSWORD_BYTE_LENGTH          = 32
-	SSH_RSA_HOST_KEY_BITS             = 2048
-	SSH_HANDSHAKE_TIMEOUT             = 30 * time.Second
-	SSH_CONNECTION_READ_DEADLINE      = 5 * time.Minute
-	SSH_TCP_PORT_FORWARD_DIAL_TIMEOUT = 30 * time.Second
-	SSH_OBFUSCATED_KEY_BYTE_LENGTH    = 32
-	REDIS_POOL_MAX_IDLE               = 50
-	REDIS_POOL_MAX_ACTIVE             = 1000
-	REDIS_POOL_IDLE_TIMEOUT           = 5 * time.Minute
+	SERVER_CONFIG_FILENAME                = "psiphon-server.config"
+	SERVER_ENTRY_FILENAME                 = "serverEntry.dat"
+	DEFAULT_SERVER_IP_ADDRESS             = "127.0.0.1"
+	WEB_SERVER_SECRET_BYTE_LENGTH         = 32
+	DISCOVERY_VALUE_KEY_BYTE_LENGTH       = 32
+	WEB_SERVER_READ_TIMEOUT               = 10 * time.Second
+	WEB_SERVER_WRITE_TIMEOUT              = 10 * time.Second
+	SSH_USERNAME_SUFFIX_BYTE_LENGTH       = 8
+	SSH_PASSWORD_BYTE_LENGTH              = 32
+	SSH_RSA_HOST_KEY_BITS                 = 2048
+	SSH_HANDSHAKE_TIMEOUT                 = 30 * time.Second
+	SSH_CONNECTION_READ_DEADLINE          = 5 * time.Minute
+	SSH_TCP_PORT_FORWARD_DIAL_TIMEOUT     = 30 * time.Second
+	SSH_TCP_PORT_FORWARD_COPY_BUFFER_SIZE = 8192
+	SSH_OBFUSCATED_KEY_BYTE_LENGTH        = 32
+	REDIS_POOL_MAX_IDLE                   = 50
+	REDIS_POOL_MAX_ACTIVE                 = 1000
+	REDIS_POOL_IDLE_TIMEOUT               = 5 * time.Minute
 )
 )
 
 
 // TODO: break config into sections (sub-structs)
 // TODO: break config into sections (sub-structs)

+ 7 - 3
psiphon/server/tunnelServer.go

@@ -716,13 +716,16 @@ func (sshClient *sshClient) handleTCPChannel(
 
 
 	// Relay channel to forwarded connection.
 	// Relay channel to forwarded connection.
 	// TODO: relay errors to fwdChannel.Stderr()?
 	// TODO: relay errors to fwdChannel.Stderr()?
-	// TODO: use a low-memory io.Copy?
 
 
 	relayWaitGroup := new(sync.WaitGroup)
 	relayWaitGroup := new(sync.WaitGroup)
 	relayWaitGroup.Add(1)
 	relayWaitGroup.Add(1)
 	go func() {
 	go func() {
 		defer relayWaitGroup.Done()
 		defer relayWaitGroup.Done()
-		bytes, err := io.Copy(fwdChannel, fwdConn)
+		// io.Copy allocates a 32K temporary buffer, and each port forward relay uses
+		// two of these buffers; using io.CopyBuffer with a smaller buffer reduces the
+		// overall memory footprint.
+		bytes, err := io.CopyBuffer(
+			fwdChannel, fwdConn, make([]byte, SSH_TCP_PORT_FORWARD_COPY_BUFFER_SIZE))
 		atomic.AddInt64(&bytesDown, bytes)
 		atomic.AddInt64(&bytesDown, bytes)
 		if err != nil && err != io.EOF {
 		if err != nil && err != io.EOF {
 			// Debug since errors such as "connection reset by peer" occur during normal operation
 			// Debug since errors such as "connection reset by peer" occur during normal operation
@@ -734,7 +737,8 @@ func (sshClient *sshClient) handleTCPChannel(
 		// be flowing?
 		// be flowing?
 		fwdChannel.Close()
 		fwdChannel.Close()
 	}()
 	}()
-	bytes, err := io.Copy(fwdConn, fwdChannel)
+	bytes, err := io.CopyBuffer(
+		fwdConn, fwdChannel, make([]byte, SSH_TCP_PORT_FORWARD_COPY_BUFFER_SIZE))
 	atomic.AddInt64(&bytesUp, bytes)
 	atomic.AddInt64(&bytesUp, bytes)
 	if err != nil && err != io.EOF {
 	if err != nil && err != io.EOF {
 		log.WithContextFields(LogFields{"error": err}).Debug("upstream TCP relay failed")
 		log.WithContextFields(LogFields{"error": err}).Debug("upstream TCP relay failed")