padding_impl.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // padding_impl.go - Padding implementation common routines.
  2. // Copyright (C) 2016 Yawning Angel.
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as
  6. // published by the Free Software Foundation, either version 3 of the
  7. // License, or (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. package basket2
  17. import (
  18. "bytes"
  19. "git.schwanenlied.me/yawning/basket2.git/framing"
  20. )
  21. type paddingImpl interface {
  22. Write([]byte) (int, error)
  23. Read([]byte) (int, error)
  24. OnClose()
  25. }
  26. func paddingImplGenericRead(conn *commonConn, recvBuf *bytes.Buffer, b []byte) (n int, err error) {
  27. // This buffering strategy will return short reads, since a new record
  28. // is only consumed off the network once the entirety of the previous
  29. // record has been returned. A goroutine that consumes off the network
  30. // instead would minimize this, but this is simple and prevents rampant
  31. // runaway buffer growth.
  32. // Refill the receive buffer as needed...
  33. for recvBuf.Len() == 0 && err == nil {
  34. // ... by reading the next record off the network...
  35. var cmd byte
  36. var msg []byte
  37. cmd, msg, err = conn.RecvRawRecord()
  38. if err != nil {
  39. break
  40. }
  41. if cmd != framing.CmdData {
  42. return 0, ErrInvalidCmd
  43. }
  44. // ... and stashing it in the buffer.
  45. if len(msg) > 0 {
  46. recvBuf.Write(msg)
  47. }
  48. }
  49. // Service the Read using buffered payload.
  50. if recvBuf.Len() > 0 && err == nil {
  51. n, _ = recvBuf.Read(b)
  52. }
  53. return
  54. }