From 3b6e614dc3b11e915bf1d77c20e87bb374839fbb Mon Sep 17 00:00:00 2001
From: Anmol Sethi <hi@nhooyr.io>
Date: Wed, 6 Nov 2019 10:02:41 -0500
Subject: [PATCH] Rename xor to mask

---
 conn.go             | 10 +++++-----
 conn_export_test.go |  2 +-
 frame.go            |  6 ++++--
 frame_test.go       | 15 +++++++--------
 4 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/conn.go b/conn.go
index 90a5a6a..26906c7 100644
--- a/conn.go
+++ b/conn.go
@@ -325,7 +325,7 @@ func (c *Conn) handleControl(ctx context.Context, h header) error {
 	}
 
 	if h.masked {
-		fastXOR(h.maskKey, b)
+		mask(h.maskKey, b)
 	}
 
 	switch h.opcode {
@@ -446,8 +446,8 @@ func (c *Conn) reader(ctx context.Context, lock bool) (MessageType, io.Reader, e
 
 	c.readerMsgCtx = ctx
 	c.readerMsgHeader = h
-	c.readerMaskKey = h.maskKey
 	c.readerFrameEOF = false
+	c.readerMaskKey = h.maskKey
 	c.readMsgLeft = c.msgReadLimit.Load()
 
 	r := &messageReader{
@@ -546,7 +546,7 @@ func (r *messageReader) read(p []byte, lock bool) (int, error) {
 	h.payloadLength -= int64(n)
 	r.c.readMsgLeft -= int64(n)
 	if h.masked {
-		r.c.readerMaskKey = fastXOR(r.c.readerMaskKey, p)
+		r.c.readerMaskKey = mask(r.c.readerMaskKey, p)
 	}
 	r.c.readerMsgHeader = h
 
@@ -762,7 +762,7 @@ func (c *Conn) writeFrame(ctx context.Context, fin bool, opcode opcode, p []byte
 	c.writeHeader.payloadLength = int64(len(p))
 
 	if c.client {
-		err = binary.Read(rand.Reader, binary.BigEndian, &c.writeHeader.maskKey)
+		err = binary.Read(rand.Reader, binary.LittleEndian, &c.writeHeader.maskKey)
 		if err != nil {
 			return 0, fmt.Errorf("failed to generate masking key: %w", err)
 		}
@@ -832,7 +832,7 @@ func (c *Conn) realWriteFrame(ctx context.Context, h header, p []byte) (n int, e
 				return n, err
 			}
 
-			maskKey = fastXOR(maskKey, c.writeBuf[i:i+n2])
+			maskKey = mask(maskKey, c.writeBuf[i:i+n2])
 
 			p = p[n2:]
 			n += n2
diff --git a/conn_export_test.go b/conn_export_test.go
index 9335381..d5f5aa2 100644
--- a/conn_export_test.go
+++ b/conn_export_test.go
@@ -37,7 +37,7 @@ func (c *Conn) ReadFrame(ctx context.Context) (OpCode, []byte, error) {
 		return 0, nil, err
 	}
 	if h.masked {
-		fastXOR(h.maskKey, b)
+		mask(h.maskKey, b)
 	}
 	return OpCode(h.opcode), b, nil
 }
diff --git a/frame.go b/frame.go
index 5345d51..a823d28 100644
--- a/frame.go
+++ b/frame.go
@@ -322,7 +322,7 @@ func (ce CloseError) bytes() ([]byte, error) {
 	return buf, nil
 }
 
-// fastXOR applies the WebSocket masking algorithm to p
+// fastMask applies the WebSocket masking algorithm to p
 // with the given key.
 // See https://tools.ietf.org/html/rfc6455#section-5.3
 //
@@ -331,7 +331,9 @@ func (ce CloseError) bytes() ([]byte, error) {
 //
 // It is optimized for LittleEndian and expects the key
 // to be in little endian.
-func fastXOR(key uint32, b []byte) uint32 {
+//
+// See https://github.com/golang/go/issues/31586
+func mask(key uint32, b []byte) uint32 {
 	if len(b) >= 8 {
 		key64 := uint64(key)<<32 | uint64(key)
 
diff --git a/frame_test.go b/frame_test.go
index c8f4cd8..2f3d4df 100644
--- a/frame_test.go
+++ b/frame_test.go
@@ -308,13 +308,13 @@ func Test_validWireCloseCode(t *testing.T) {
 	}
 }
 
-func Test_xor(t *testing.T) {
+func Test_mask(t *testing.T) {
 	t.Parallel()
 
 	key := []byte{0xa, 0xb, 0xc, 0xff}
 	key32 := binary.LittleEndian.Uint32(key)
 	p := []byte{0xa, 0xb, 0xc, 0xf2, 0xc}
-	gotKey32 := fastXOR(key32, p)
+	gotKey32 := mask(key32, p)
 
 	if exp := []byte{0, 0, 0, 0x0d, 0x6}; !cmp.Equal(exp, p) {
 		t.Fatalf("unexpected mask: %v", cmp.Diff(exp, p))
@@ -325,7 +325,7 @@ func Test_xor(t *testing.T) {
 	}
 }
 
-func basixXOR(maskKey [4]byte, pos int, b []byte) int {
+func basixMask(maskKey [4]byte, pos int, b []byte) int {
 	for i := range b {
 		b[i] ^= maskKey[pos&3]
 		pos++
@@ -333,7 +333,7 @@ func basixXOR(maskKey [4]byte, pos int, b []byte) int {
 	return pos & 3
 }
 
-func BenchmarkXOR(b *testing.B) {
+func Benchmark_mask(b *testing.B) {
 	sizes := []int{
 		2,
 		3,
@@ -355,18 +355,18 @@ func BenchmarkXOR(b *testing.B) {
 			name: "basic",
 			fn: func(b *testing.B, key [4]byte, p []byte) {
 				for i := 0; i < b.N; i++ {
-					basixXOR(key, 0, p)
+					basixMask(key, 0, p)
 				}
 			},
 		},
 		{
 			name: "fast",
 			fn: func(b *testing.B, key [4]byte, p []byte) {
-				key32 := binary.BigEndian.Uint32(key[:])
+				key32 := binary.LittleEndian.Uint32(key[:])
 				b.ResetTimer()
 
 				for i := 0; i < b.N; i++ {
-					fastXOR(key32, p)
+					mask(key32, p)
 				}
 			},
 		},
@@ -384,7 +384,6 @@ func BenchmarkXOR(b *testing.B) {
 		b.Run(strconv.Itoa(size), func(b *testing.B) {
 			for _, fn := range fns {
 				b.Run(fn.name, func(b *testing.B) {
-					b.ReportAllocs()
 					b.SetBytes(int64(size))
 
 					fn.fn(b, key, p)
-- 
GitLab