protocol.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package quic
  2. import (
  3. "fmt"
  4. "io"
  5. )
  6. // protocolSignature defines the first 6 bytes of the stream, which is used to distinguish the type of stream. It
  7. // ensures whoever performs a handshake does not write data before writing the metadata.
  8. type protocolSignature [6]byte
  9. var (
  10. // dataStreamProtocolSignature is a custom protocol signature for data stream
  11. dataStreamProtocolSignature = protocolSignature{0x0A, 0x36, 0xCD, 0x12, 0xA1, 0x3E}
  12. // rpcStreamProtocolSignature is a custom protocol signature for RPC stream
  13. rpcStreamProtocolSignature = protocolSignature{0x52, 0xBB, 0x82, 0x5C, 0xDB, 0x65}
  14. errDataStreamNotSupported = fmt.Errorf("data protocol not supported")
  15. errRPCStreamNotSupported = fmt.Errorf("rpc protocol not supported")
  16. )
  17. type protocolVersion string
  18. const (
  19. protocolV1 protocolVersion = "01"
  20. protocolVersionLength = 2
  21. )
  22. // determineProtocol reads the first 6 bytes from the stream to determine which protocol is spoken by the client.
  23. // The protocols are magic byte arrays understood by both sides of the stream.
  24. func determineProtocol(stream io.Reader) (protocolSignature, error) {
  25. signature, err := readSignature(stream)
  26. if err != nil {
  27. return protocolSignature{}, err
  28. }
  29. switch signature {
  30. case dataStreamProtocolSignature:
  31. return dataStreamProtocolSignature, nil
  32. case rpcStreamProtocolSignature:
  33. return rpcStreamProtocolSignature, nil
  34. default:
  35. return protocolSignature{}, fmt.Errorf("unknown signature %v", signature)
  36. }
  37. }
  38. func writeDataStreamPreamble(stream io.Writer) error {
  39. if err := writeSignature(stream, dataStreamProtocolSignature); err != nil {
  40. return err
  41. }
  42. return writeVersion(stream)
  43. }
  44. func writeVersion(stream io.Writer) error {
  45. _, err := stream.Write([]byte(protocolV1)[:protocolVersionLength])
  46. return err
  47. }
  48. func readVersion(stream io.Reader) (string, error) {
  49. version := make([]byte, protocolVersionLength)
  50. _, err := stream.Read(version)
  51. return string(version), err
  52. }
  53. func readSignature(stream io.Reader) (protocolSignature, error) {
  54. var signature protocolSignature
  55. if _, err := io.ReadFull(stream, signature[:]); err != nil {
  56. return protocolSignature{}, err
  57. }
  58. return signature, nil
  59. }
  60. func writeSignature(stream io.Writer, signature protocolSignature) error {
  61. _, err := stream.Write(signature[:])
  62. return err
  63. }