protocol.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
  2. package protocol
  3. import (
  4. "errors"
  5. "fmt"
  6. "io"
  7. )
  8. const (
  9. magic = 0x9E79BC40
  10. ProtocolName = "bep-relay"
  11. )
  12. var (
  13. ResponseSuccess = Response{0, "success"}
  14. ResponseNotFound = Response{1, "not found"}
  15. ResponseAlreadyConnected = Response{2, "already connected"}
  16. ResponseWrongToken = Response{3, "wrong token"}
  17. ResponseUnexpectedMessage = Response{100, "unexpected message"}
  18. )
  19. func WriteMessage(w io.Writer, message interface{}) error {
  20. header := header{
  21. magic: magic,
  22. }
  23. var payload []byte
  24. var err error
  25. switch msg := message.(type) {
  26. case Ping:
  27. payload, err = msg.MarshalXDR()
  28. header.messageType = messageTypePing
  29. case Pong:
  30. payload, err = msg.MarshalXDR()
  31. header.messageType = messageTypePong
  32. case JoinRelayRequest:
  33. payload, err = msg.MarshalXDR()
  34. header.messageType = messageTypeJoinRelayRequest
  35. case JoinSessionRequest:
  36. payload, err = msg.MarshalXDR()
  37. header.messageType = messageTypeJoinSessionRequest
  38. case Response:
  39. payload, err = msg.MarshalXDR()
  40. header.messageType = messageTypeResponse
  41. case ConnectRequest:
  42. payload, err = msg.MarshalXDR()
  43. header.messageType = messageTypeConnectRequest
  44. case SessionInvitation:
  45. payload, err = msg.MarshalXDR()
  46. header.messageType = messageTypeSessionInvitation
  47. case RelayFull:
  48. payload, err = msg.MarshalXDR()
  49. header.messageType = messageTypeRelayFull
  50. default:
  51. err = errors.New("unknown message type")
  52. }
  53. if err != nil {
  54. return err
  55. }
  56. header.messageLength = int32(len(payload))
  57. headerpayload, err := header.MarshalXDR()
  58. if err != nil {
  59. return err
  60. }
  61. _, err = w.Write(append(headerpayload, payload...))
  62. return err
  63. }
  64. func ReadMessage(r io.Reader) (interface{}, error) {
  65. var header header
  66. buf := make([]byte, header.XDRSize())
  67. if _, err := io.ReadFull(r, buf); err != nil {
  68. return nil, err
  69. }
  70. if err := header.UnmarshalXDR(buf); err != nil {
  71. return nil, err
  72. }
  73. if header.magic != magic {
  74. return nil, errors.New("magic mismatch")
  75. }
  76. if header.messageLength < 0 || header.messageLength > 1024 {
  77. return nil, fmt.Errorf("bad length (%d)", header.messageLength)
  78. }
  79. buf = make([]byte, int(header.messageLength))
  80. if _, err := io.ReadFull(r, buf); err != nil {
  81. return nil, err
  82. }
  83. switch header.messageType {
  84. case messageTypePing:
  85. var msg Ping
  86. err := msg.UnmarshalXDR(buf)
  87. return msg, err
  88. case messageTypePong:
  89. var msg Pong
  90. err := msg.UnmarshalXDR(buf)
  91. return msg, err
  92. case messageTypeJoinRelayRequest:
  93. var msg JoinRelayRequest
  94. // In prior versions of the protocol JoinRelayRequest did not have a
  95. // token field. Trying to unmarshal such a request will result in
  96. // an error, return msg with an empty token instead.
  97. if header.messageLength == 0 {
  98. return msg, nil
  99. }
  100. err := msg.UnmarshalXDR(buf)
  101. return msg, err
  102. case messageTypeJoinSessionRequest:
  103. var msg JoinSessionRequest
  104. err := msg.UnmarshalXDR(buf)
  105. return msg, err
  106. case messageTypeResponse:
  107. var msg Response
  108. err := msg.UnmarshalXDR(buf)
  109. return msg, err
  110. case messageTypeConnectRequest:
  111. var msg ConnectRequest
  112. err := msg.UnmarshalXDR(buf)
  113. return msg, err
  114. case messageTypeSessionInvitation:
  115. var msg SessionInvitation
  116. err := msg.UnmarshalXDR(buf)
  117. return msg, err
  118. case messageTypeRelayFull:
  119. var msg RelayFull
  120. err := msg.UnmarshalXDR(buf)
  121. return msg, err
  122. }
  123. return nil, errors.New("unknown message type")
  124. }