mask.go raw

   1  // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.  Use of
   2  // this source code is governed by a BSD-style license that can be found in the
   3  // LICENSE file.
   4  
   5  //go:build !appengine
   6  // +build !appengine
   7  
   8  package websocket
   9  
  10  import "unsafe"
  11  
  12  const wordSize = int(unsafe.Sizeof(uintptr(0)))
  13  
  14  func maskBytes(key [4]byte, pos int, b []byte) int {
  15  	// Mask one byte at a time for small buffers.
  16  	if len(b) < 2*wordSize {
  17  		for i := range b {
  18  			b[i] ^= key[pos&3]
  19  			pos++
  20  		}
  21  		return pos & 3
  22  	}
  23  
  24  	// Mask one byte at a time to word boundary.
  25  	if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 {
  26  		n = wordSize - n
  27  		for i := range b[:n] {
  28  			b[i] ^= key[pos&3]
  29  			pos++
  30  		}
  31  		b = b[n:]
  32  	}
  33  
  34  	// Create aligned word size key.
  35  	var k [wordSize]byte
  36  	for i := range k {
  37  		k[i] = key[(pos+i)&3]
  38  	}
  39  	kw := *(*uintptr)(unsafe.Pointer(&k))
  40  
  41  	// Mask one word at a time.
  42  	n := (len(b) / wordSize) * wordSize
  43  	for i := 0; i < n; i += wordSize {
  44  		*(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw
  45  	}
  46  
  47  	// Mask one byte at a time for remaining bytes.
  48  	b = b[n:]
  49  	for i := range b {
  50  		b[i] ^= key[pos&3]
  51  		pos++
  52  	}
  53  
  54  	return pos & 3
  55  }
  56