mask.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  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. package websocket
  5. import (
  6. "math/rand"
  7. "unsafe"
  8. )
  9. const wordSize = int(unsafe.Sizeof(uintptr(0)))
  10. func newMaskKey() [4]byte {
  11. n := rand.Uint32()
  12. return [4]byte{byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 24)}
  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. // Mask one byte at a time to word boundary.
  24. if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 {
  25. n = wordSize - n
  26. for i := range b[:n] {
  27. b[i] ^= key[pos&3]
  28. pos++
  29. }
  30. b = b[n:]
  31. }
  32. // Create aligned word size key.
  33. var k [wordSize]byte
  34. for i := range k {
  35. k[i] = key[(pos+i)&3]
  36. }
  37. kw := *(*uintptr)(unsafe.Pointer(&k))
  38. // Mask one word at a time.
  39. n := (len(b) / wordSize) * wordSize
  40. for i := 0; i < n; i += wordSize {
  41. *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw
  42. }
  43. // Mask one byte at a time for remaining bytes.
  44. b = b[n:]
  45. for i := range b {
  46. b[i] ^= key[pos&3]
  47. pos++
  48. }
  49. return pos & 3
  50. }