client.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. //Package for communication with the snowflake broker
  2. // import "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/messages"
  3. package messages
  4. import (
  5. "bytes"
  6. "encoding/json"
  7. "fmt"
  8. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/bridgefingerprint"
  9. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/nat"
  10. )
  11. const ClientVersion = "1.0"
  12. /* Client--Broker protocol v1.x specification:
  13. All messages contain the version number
  14. followed by a new line and then the message body
  15. <message> := <version>\n<body>
  16. <version> := <digit>.<digit>
  17. <body> := <poll request>|<poll response>
  18. There are two different types of body messages,
  19. each encoded in JSON format
  20. == ClientPollRequest ==
  21. <poll request> :=
  22. {
  23. offer: <sdp offer>
  24. [nat: (unknown|restricted|unrestricted)]
  25. [fingerprint: <fingerprint string>]
  26. }
  27. The NAT field is optional, and if it is missing a
  28. value of "unknown" will be assumed. The fingerprint
  29. is also optional and, if absent, will be assigned the
  30. fingerprint of the default bridge.
  31. == ClientPollResponse ==
  32. <poll response> :=
  33. {
  34. [answer: <sdp answer>]
  35. [error: <error string>]
  36. }
  37. If the broker succeeded in matching the client with a proxy,
  38. the answer field MUST contain a valid SDP answer, and the
  39. error field MUST be empty. If the answer field is empty, the
  40. error field MUST contain a string explaining with a reason
  41. for the error.
  42. */
  43. // The bridge fingerprint to assume, for client poll requests that do not
  44. // specify a fingerprint. Before #28651, there was only one bridge with one
  45. // fingerprint, which all clients expected to be connected to implicitly.
  46. // If a client is old enough that it does not specify a fingerprint, this is
  47. // the fingerprint it expects. Clients that do set a fingerprint in the
  48. // SOCKS params will also be assumed to want to connect to the default bridge.
  49. const defaultBridgeFingerprint = "2B280B23E1107BB62ABFC40DDCC8824814F80A72"
  50. type ClientPollRequest struct {
  51. Offer string `json:"offer"`
  52. NAT string `json:"nat"`
  53. Fingerprint string `json:"fingerprint"`
  54. }
  55. // Encodes a poll message from a snowflake client
  56. func (req *ClientPollRequest) EncodeClientPollRequest() ([]byte, error) {
  57. if req.Fingerprint == "" {
  58. req.Fingerprint = defaultBridgeFingerprint
  59. }
  60. body, err := json.Marshal(req)
  61. if err != nil {
  62. return nil, err
  63. }
  64. return append([]byte(ClientVersion+"\n"), body...), nil
  65. }
  66. // Decodes a poll message from a snowflake client
  67. func DecodeClientPollRequest(data []byte) (*ClientPollRequest, error) {
  68. parts := bytes.SplitN(data, []byte("\n"), 2)
  69. if len(parts) < 2 {
  70. // no version number found
  71. return nil, fmt.Errorf("unsupported message version")
  72. }
  73. var message ClientPollRequest
  74. if string(parts[0]) != ClientVersion {
  75. return nil, fmt.Errorf("unsupported message version")
  76. }
  77. err := json.Unmarshal(parts[1], &message)
  78. if err != nil {
  79. return nil, err
  80. }
  81. if message.Offer == "" {
  82. return nil, fmt.Errorf("no supplied offer")
  83. }
  84. if message.Fingerprint == "" {
  85. message.Fingerprint = defaultBridgeFingerprint
  86. }
  87. if _, err := bridgefingerprint.FingerprintFromHexString(message.Fingerprint); err != nil {
  88. return nil, fmt.Errorf("cannot decode fingerprint")
  89. }
  90. switch message.NAT {
  91. case "":
  92. message.NAT = nat.NATUnknown
  93. case nat.NATUnknown:
  94. case nat.NATRestricted:
  95. case nat.NATUnrestricted:
  96. default:
  97. return nil, fmt.Errorf("invalid NAT type")
  98. }
  99. return &message, nil
  100. }
  101. type ClientPollResponse struct {
  102. Answer string `json:"answer,omitempty"`
  103. Error string `json:"error,omitempty"`
  104. }
  105. // Encodes a poll response for a snowflake client
  106. func (resp *ClientPollResponse) EncodePollResponse() ([]byte, error) {
  107. return json.Marshal(resp)
  108. }
  109. // Decodes a poll response for a snowflake client
  110. // If the Error field is empty, the Answer should be non-empty
  111. func DecodeClientPollResponse(data []byte) (*ClientPollResponse, error) {
  112. var message ClientPollResponse
  113. err := json.Unmarshal(data, &message)
  114. if err != nil {
  115. return nil, err
  116. }
  117. if message.Error == "" && message.Answer == "" {
  118. return nil, fmt.Errorf("received empty broker response")
  119. }
  120. return &message, nil
  121. }