Browse Source

Carve off the read side code into a common routine for reuse.

Yawning Angel 3 years ago
parent
commit
0d4b23e5e8
4 changed files with 66 additions and 37 deletions
  1. 1 7
      common.go
  2. 2 0
      internal/discretedist/discrete_dist.go
  3. 62 0
      padding_impl.go
  4. 1 30
      padding_null.go

+ 1 - 7
common.go

@@ -77,12 +77,6 @@ var (
 // PaddingMethod is a given padding algorithm identifier.
 type PaddingMethod byte
 
-type paddingImpl interface {
-	Write([]byte) (int, error)
-	Read([]byte) (int, error)
-	OnClose()
-}
-
 // AuthPolicy is the server authentication policy.
 type AuthPolicy byte
 
@@ -160,7 +154,7 @@ func (c *commonConn) Read(p []byte) (n int, err error) {
 	n, err = c.impl.Read(p)
 	if c.enableReadDelay && n > 0 {
 		// If data payload was received and read delay is enabled,
-		// delay for a random interval [0, 2 * tau] usec.
+		// delay for a random interval [0, 2 * tau) usec.
 		//
 		// This is primarily intended for the server side of the Tor
 		// Pluggable transport code in an attempt to mitigate delay based

+ 2 - 0
internal/discretedist/discrete_dist.go

@@ -153,6 +153,8 @@ func (d *DiscreteDist) Sample(r *mrand.Rand) int {
 	return d.values[idx]
 }
 
+// NewUniform creates a new uniform discrete distribution, optionally with
+// biased probabilities.
 func NewUniform(r *mrand.Rand, minValue, maxValue, maxN int, biased bool) *DiscreteDist {
 	d := new(DiscreteDist)
 

+ 62 - 0
padding_impl.go

@@ -0,0 +1,62 @@
+// padding_impl.go - Padding implementation common routines.
+// Copyright (C) 2016  Yawning Angel.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package basket2
+
+import (
+	"bytes"
+
+	"git.schwanenlied.me/yawning/basket2.git/framing"
+)
+
+type paddingImpl interface {
+	Write([]byte) (int, error)
+	Read([]byte) (int, error)
+	OnClose()
+}
+
+func paddingImplGenericRead(conn *commonConn, recvBuf *bytes.Buffer, p []byte) (n int, err error) {
+	// This buffering strategy will return short reads, since a new record
+	// is only consumed off the network once the entirety of the previous
+	// record has been returned.  A goroutine that consumes off the network
+	// instead would minimize this, but this is simple and prevents rampant
+	// runaway buffer growth.
+
+	// Refill the receive buffer as needed...
+	for recvBuf.Len() == 0 && err == nil {
+		// ... by reading the next record off the network...
+		var cmd byte
+		var msg []byte
+		cmd, msg, err = conn.RecvRawRecord()
+		if err != nil {
+			break
+		}
+		if cmd != framing.CmdData {
+			return 0, ErrInvalidCmd
+		}
+
+		// ... and stashing it in the buffer.
+		if len(msg) > 0 {
+			recvBuf.Write(msg)
+		}
+	}
+
+	// Service the Read using buffered payload.
+	if recvBuf.Len() > 0 && err == nil {
+		n, _ = recvBuf.Read(p)
+	}
+	return
+}

+ 1 - 30
padding_null.go

@@ -61,36 +61,7 @@ func (c *nullPadding) Write(p []byte) (int, error) {
 }
 
 func (c *nullPadding) Read(p []byte) (n int, err error) {
-	// This buffering strategy will return short reads, since a new record
-	// is only consumed off the network once the entirety of the previous
-	// record has been returned.  A goroutine that comsumes off the network
-	// instead would minimize this, but this is simple and prevents rampant
-	// runaway buffer growth.
-
-	// Refill the receive buffer as needed...
-	for c.recvBuf.Len() == 0 && err == nil {
-		// ... by reading the next record off the network...
-		var cmd byte
-		var msg []byte
-		cmd, msg, err = c.conn.RecvRawRecord()
-		if err != nil {
-			break
-		}
-		if cmd != framing.CmdData {
-			return 0, ErrInvalidCmd
-		}
-
-		// ... and stashing it in the buffer.
-		if len(msg) > 0 {
-			c.recvBuf.Write(msg)
-		}
-	}
-
-	// Service the Read using buffered payload.
-	if c.recvBuf.Len() > 0 && err == nil {
-		n, _ = c.recvBuf.Read(p)
-	}
-	return
+	return paddingImplGenericRead(c.conn, &c.recvBuf, p)
 }
 
 func (c *nullPadding) OnClose() {