diff --git a/broker/bridge-list.go b/broker/bridge-list.go index 3913a2e..e77db65 100644 --- a/broker/bridge-list.go +++ b/broker/bridge-list.go @@ -1,6 +1,20 @@ package main -import "sync" +import ( + "bufio" + "encoding/hex" + "encoding/json" + "errors" + "io" + "sync" +) + +var ErrBridgeNotFound = errors.New("bridge not found") +var ErrBridgeFingerprintInvalid = errors.New("bridge fingerprint invalid") + +func NewBridgeListHolder() BridgeListHolderFileBased { + return &bridgeListHolder{} +} type bridgeListHolder struct { bridgeInfo map[[20]byte]BridgeInfo @@ -11,8 +25,45 @@ type BridgeListHolder interface { GetBridgeInfo(fingerprint [20]byte) (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 [20]byte) (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[[20]byte]BridgeInfo{} + inputScanner := bufio.NewScanner(reader) + for inputScanner.Scan() { + inputLine := inputScanner.Bytes() + bridgeInfo := BridgeInfo{} + if err := json.Unmarshal(inputLine, &bridgeInfo); err != nil { + return err + } + var bridgeHash [20]byte + if n, err := hex.Decode(bridgeHash[:], []byte(bridgeInfo.Fingerprint)); err != nil { + return err + } else if n != 20 { + return ErrBridgeFingerprintInvalid + } + bridgeInfoMap[bridgeHash] = bridgeInfo + } + h.accessBridgeInfo.Lock() + defer h.accessBridgeInfo.Unlock() + h.bridgeInfo = bridgeInfoMap + return nil +}