bridge-list.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /* (*BridgeListHolderFileBased).LoadBridgeInfo loads a Snowflake Server bridge info description file,
  2. its format is as follows:
  3. This file should be in newline-delimited JSON format(https://jsonlines.org/).
  4. For each line, the format of json data should be in the format of:
  5. {"displayName":"default", "webSocketAddress":"wss://snowflake.torproject.net/", "fingerprint":"2B280B23E1107BB62ABFC40DDCC8824814F80A72"}
  6. displayName:string is the name of this bridge. This value is not currently used programmatically.
  7. webSocketAddress:string is the WebSocket URL of this bridge.
  8. This will be the address proxy used to connect to this snowflake server.
  9. fingerprint:string is the identifier of the bridge.
  10. This will be used by a client to identify the bridge it wishes to connect to.
  11. The existence of ANY other fields is NOT permitted.
  12. The file will be considered invalid if there is at least one invalid json record.
  13. In this case, an error will be returned, and none of the records will be loaded.
  14. */
  15. package main
  16. import (
  17. "bufio"
  18. "bytes"
  19. "encoding/json"
  20. "errors"
  21. "io"
  22. "sync"
  23. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/bridgefingerprint"
  24. )
  25. var ErrBridgeNotFound = errors.New("bridge with requested fingerprint is unknown to the broker")
  26. func NewBridgeListHolder() BridgeListHolderFileBased {
  27. return &bridgeListHolder{}
  28. }
  29. type bridgeListHolder struct {
  30. bridgeInfo map[bridgefingerprint.Fingerprint]BridgeInfo
  31. accessBridgeInfo sync.RWMutex
  32. }
  33. type BridgeListHolder interface {
  34. GetBridgeInfo(bridgefingerprint.Fingerprint) (BridgeInfo, error)
  35. }
  36. type BridgeListHolderFileBased interface {
  37. BridgeListHolder
  38. LoadBridgeInfo(reader io.Reader) error
  39. }
  40. type BridgeInfo struct {
  41. DisplayName string `json:"displayName"`
  42. WebSocketAddress string `json:"webSocketAddress"`
  43. Fingerprint string `json:"fingerprint"`
  44. }
  45. func (h *bridgeListHolder) GetBridgeInfo(fingerprint bridgefingerprint.Fingerprint) (BridgeInfo, error) {
  46. h.accessBridgeInfo.RLock()
  47. defer h.accessBridgeInfo.RUnlock()
  48. if bridgeInfo, ok := h.bridgeInfo[fingerprint]; ok {
  49. return bridgeInfo, nil
  50. }
  51. return BridgeInfo{}, ErrBridgeNotFound
  52. }
  53. func (h *bridgeListHolder) LoadBridgeInfo(reader io.Reader) error {
  54. bridgeInfoMap := map[bridgefingerprint.Fingerprint]BridgeInfo{}
  55. inputScanner := bufio.NewScanner(reader)
  56. for inputScanner.Scan() {
  57. inputLine := inputScanner.Bytes()
  58. bridgeInfo := BridgeInfo{}
  59. decoder := json.NewDecoder(bytes.NewReader(inputLine))
  60. decoder.DisallowUnknownFields()
  61. if err := decoder.Decode(&bridgeInfo); err != nil {
  62. return err
  63. }
  64. var bridgeFingerprint bridgefingerprint.Fingerprint
  65. var err error
  66. if bridgeFingerprint, err = bridgefingerprint.FingerprintFromHexString(bridgeInfo.Fingerprint); err != nil {
  67. return err
  68. }
  69. bridgeInfoMap[bridgeFingerprint] = bridgeInfo
  70. }
  71. h.accessBridgeInfo.Lock()
  72. defer h.accessBridgeInfo.Unlock()
  73. h.bridgeInfo = bridgeInfoMap
  74. return nil
  75. }