capsule.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package http3
  2. import (
  3. "io"
  4. "github.com/Psiphon-Labs/quic-go/quicvarint"
  5. )
  6. // CapsuleType is the type of the capsule.
  7. type CapsuleType uint64
  8. type exactReader struct {
  9. R *io.LimitedReader
  10. }
  11. func (r *exactReader) Read(b []byte) (int, error) {
  12. n, err := r.R.Read(b)
  13. if r.R.N > 0 {
  14. return n, io.ErrUnexpectedEOF
  15. }
  16. return n, err
  17. }
  18. // ParseCapsule parses the header of a Capsule.
  19. // It returns an io.LimitedReader that can be used to read the Capsule value.
  20. // The Capsule value must be read entirely (i.e. until the io.EOF) before using r again.
  21. func ParseCapsule(r quicvarint.Reader) (CapsuleType, io.Reader, error) {
  22. ct, err := quicvarint.Read(r)
  23. if err != nil {
  24. if err == io.EOF {
  25. return 0, nil, io.ErrUnexpectedEOF
  26. }
  27. return 0, nil, err
  28. }
  29. l, err := quicvarint.Read(r)
  30. if err != nil {
  31. if err == io.EOF {
  32. return 0, nil, io.ErrUnexpectedEOF
  33. }
  34. return 0, nil, err
  35. }
  36. return CapsuleType(ct), &exactReader{R: io.LimitReader(r, int64(l)).(*io.LimitedReader)}, nil
  37. }
  38. // WriteCapsule writes a capsule
  39. func WriteCapsule(w quicvarint.Writer, ct CapsuleType, value []byte) error {
  40. b := make([]byte, 0, 16)
  41. b = quicvarint.Append(b, uint64(ct))
  42. b = quicvarint.Append(b, uint64(len(value)))
  43. if _, err := w.Write(b); err != nil {
  44. return err
  45. }
  46. _, err := w.Write(value)
  47. return err
  48. }