mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 11:11:30 -04:00
94 lines
2.9 KiB
Go
94 lines
2.9 KiB
Go
/* (*BridgeListHolderFileBased).LoadBridgeInfo loads a Snowflake Server bridge info description file,
|
|
its format is as follows:
|
|
|
|
This file should be in newline-delimited JSON format(https://jsonlines.org/).
|
|
For each line, the format of json data should be in the format of:
|
|
{"displayName":"default", "webSocketAddress":"wss://snowflake.torproject.net/", "fingerprint":"2B280B23E1107BB62ABFC40DDCC8824814F80A72"}
|
|
|
|
displayName:string is the name of this bridge. This value is not currently used programmatically.
|
|
|
|
webSocketAddress:string is the WebSocket URL of this bridge.
|
|
This will be the address proxy used to connect to this snowflake server.
|
|
|
|
fingerprint:string is the identifier of the bridge.
|
|
This will be used by a client to identify the bridge it wishes to connect to.
|
|
|
|
The existence of ANY other fields is NOT permitted.
|
|
|
|
The file will be considered invalid if there is at least one invalid json record.
|
|
In this case, an error will be returned, and none of the records will be loaded.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"sync"
|
|
|
|
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/bridgefingerprint"
|
|
)
|
|
|
|
var ErrBridgeNotFound = errors.New("bridge with requested fingerprint is unknown to the broker")
|
|
|
|
func NewBridgeListHolder() BridgeListHolderFileBased {
|
|
return &bridgeListHolder{}
|
|
}
|
|
|
|
type bridgeListHolder struct {
|
|
bridgeInfo map[bridgefingerprint.Fingerprint]BridgeInfo
|
|
accessBridgeInfo sync.RWMutex
|
|
}
|
|
|
|
type BridgeListHolder interface {
|
|
GetBridgeInfo(bridgefingerprint.Fingerprint) (BridgeInfo, error)
|
|
}
|
|
|
|
type BridgeListHolderFileBased interface {
|
|
BridgeListHolder
|
|
LoadBridgeInfo(reader io.Reader) error
|
|
}
|
|
|
|
type BridgeInfo struct {
|
|
DisplayName string `json:"displayName"`
|
|
WebSocketAddress string `json:"webSocketAddress"`
|
|
Fingerprint string `json:"fingerprint"`
|
|
}
|
|
|
|
func (h *bridgeListHolder) GetBridgeInfo(fingerprint bridgefingerprint.Fingerprint) (BridgeInfo, error) {
|
|
h.accessBridgeInfo.RLock()
|
|
defer h.accessBridgeInfo.RUnlock()
|
|
if bridgeInfo, ok := h.bridgeInfo[fingerprint]; ok {
|
|
return bridgeInfo, nil
|
|
}
|
|
return BridgeInfo{}, ErrBridgeNotFound
|
|
}
|
|
|
|
func (h *bridgeListHolder) LoadBridgeInfo(reader io.Reader) error {
|
|
bridgeInfoMap := map[bridgefingerprint.Fingerprint]BridgeInfo{}
|
|
inputScanner := bufio.NewScanner(reader)
|
|
for inputScanner.Scan() {
|
|
inputLine := inputScanner.Bytes()
|
|
bridgeInfo := BridgeInfo{}
|
|
decoder := json.NewDecoder(bytes.NewReader(inputLine))
|
|
decoder.DisallowUnknownFields()
|
|
if err := decoder.Decode(&bridgeInfo); err != nil {
|
|
return err
|
|
}
|
|
|
|
var bridgeFingerprint bridgefingerprint.Fingerprint
|
|
var err error
|
|
if bridgeFingerprint, err = bridgefingerprint.FingerprintFromHexString(bridgeInfo.Fingerprint); err != nil {
|
|
return err
|
|
}
|
|
|
|
bridgeInfoMap[bridgeFingerprint] = bridgeInfo
|
|
}
|
|
h.accessBridgeInfo.Lock()
|
|
defer h.accessBridgeInfo.Unlock()
|
|
h.bridgeInfo = bridgeInfoMap
|
|
return nil
|
|
}
|