Documentation ¶
Index ¶
- Constants
- func NewHashnode(k Hashkey, r Resource) *hashnode
- func SpeedToString(speed int) string
- func StateToString(state int) string
- type BackendResources
- func (ctx *BackendResources) Add(r1 Resource)
- func (ctx *BackendResources) Get(distName string, rType string, ipVersion IPVersion) ResourceState
- func (ctx *BackendResources) Prune(rName string) []Resource
- func (ctx *BackendResources) RegisterChan(req *ResourceRequest, recipient chan *ResourceDiff)
- func (ctx *BackendResources) UnregisterChan(distName string, recipient chan *ResourceDiff)
- type BridgeRequest
- type Collection
- type CollectionConfig
- type Dummy
- func (d *Dummy) BlockedIn() LocationSet
- func (d *Dummy) Distributor() string
- func (d *Dummy) Expiry() time.Duration
- func (d *Dummy) IPVersion() IPVersion
- func (d *Dummy) IsValid() bool
- func (d *Dummy) Oid() Hashkey
- func (d *Dummy) RelationIdentifiers() []string
- func (d *Dummy) SetBlockedIn(LocationSet)
- func (d *Dummy) SetTest(t *ResourceTest)
- func (d *Dummy) SetTestFunc(f func(Resource))
- func (d *Dummy) String() string
- func (d *Dummy) Test()
- func (d *Dummy) TestResult() *ResourceTest
- func (d *Dummy) Type() string
- func (d *Dummy) Uid() Hashkey
- type FilterFunc
- type Hashkey
- type Hashring
- func (h *Hashring) Add(r Resource) error
- func (h *Hashring) AddOrUpdate(r Resource) (event int)
- func (h *Hashring) ApplyDiff(d *ResourceDiff)
- func (h *Hashring) Clear()
- func (h *Hashring) Filter(f FilterFunc) []Resource
- func (h *Hashring) Get(k Hashkey) (Resource, error)
- func (h *Hashring) GetAll() []Resource
- func (h *Hashring) GetExact(k Hashkey) (Resource, error)
- func (h *Hashring) GetMany(k Hashkey, num int, req *BridgeRequest) (resources []Resource, err error)
- func (h *Hashring) Len() int
- func (h *Hashring) Less(i, j int) bool
- func (h *Hashring) Prune() []Resource
- func (h *Hashring) Remove(r Resource) error
- func (h *Hashring) Swap(i, j int)
- type IPVersion
- type Location
- type LocationSet
- type Resource
- type ResourceBase
- type ResourceDiff
- type ResourceDiffRecipient
- type ResourceGroup
- type ResourceMap
- type ResourceQueue
- type ResourceRequest
- type ResourceState
- type ResourceTest
- type TypeConfig
Constants ¶
const ( // These constants represent resource event types. The backend informs // distributors if a resource is new, has changed, or has disappeared. ResourceUnchanged = iota ResourceIsNew ResourceChanged ResourceIsGone ResourceError )
const ( // The following constants represent the states that a resource can be in. // Before rdsys had a chance to ask bridgestrap about a resource's state, // it's untested. Afterwards, it's either functional or not functional. StateUntested = iota StateFunctional StateDysfunctional )
const ( // The following constants act as a crude representation of the bandwidth speed // that a resource can have. This is meant as a way to check whether or not the ratio // meets the bandwidth threshold for the given resource without requiring the context. // Before an onbasca test, a resource's speed is untested. Afterwards, it's either // sufficient or insufficient. SpeedUntested = iota SpeedAccepted SpeedRejected )
Variables ¶
This section is empty.
Functions ¶
func NewHashnode ¶
NewHashnode returns a new hash node and sets its LastUpdate field to the current UTC time.
Types ¶
type BackendResources ¶
type BackendResources struct { Collection // OnlyFunctional resources will be provided to distributors OnlyFunctional bool // UseBandwidthRatio to decide wich bridges to distribute UseBandwidthRatio bool // The mutex us used to protect the access to ResourceDiffRecipients. // The hashrings in the Collection have their own mutex and the entries // of the Collection map are only set during intialization. sync.RWMutex // ResourceDiffRecipients maps a distributor name (e.g., "moat") to an resource // diff recipient struct that helps us keep track of notifying distributors when // their resources change. It is used by the resource stream API. ResourceDiffRecipients map[string][]*ResourceDiffRecipient }
BackendResources implements a collection of resources for our backend. The backend uses this data structure to keep track of all of its resource types.
func NewBackendResources ¶
func NewBackendResources(cfg *CollectionConfig) *BackendResources
NewBackendResources creates and returns a new resource collection. rTypes is a map of resource type names to a boolean indicating if the resource is unpartitioend
func (*BackendResources) Add ¶
func (ctx *BackendResources) Add(r1 Resource)
Add adds the given resource to the resource collection. If the resource already exists but has changed (i.e. its unique ID remains the same but its object ID changed), we update the existing resource.
func (*BackendResources) Get ¶
func (ctx *BackendResources) Get(distName string, rType string, ipVersion IPVersion) ResourceState
Get returns a struct that contains the state of resources distributor.
func (*BackendResources) Prune ¶
func (ctx *BackendResources) Prune(rName string) []Resource
Prune removes expired resources and notifies on not working ones
func (*BackendResources) RegisterChan ¶
func (ctx *BackendResources) RegisterChan(req *ResourceRequest, recipient chan *ResourceDiff)
RegisterChan registers a channel to be informed about resource updates.
func (*BackendResources) UnregisterChan ¶
func (ctx *BackendResources) UnregisterChan(distName string, recipient chan *ResourceDiff)
UnregisterChan unregisters a channel to be informed about resource updates.
type BridgeRequest ¶
type BridgeRequest struct { // IPVersion can be used to select only resources of IPv6 or IPv4. // In case of IPAny any resources will be returned. IPVersion IPVersion // Country is the country from where the request is being placed, // it will be used to don't return bridges known to be blocked in that country. Country string }
BridgeRequest holds the options to request a bridge from the hashring. If an empty request is created by BridgeRequest{} it should work for selecting any bridge.
type Collection ¶
type Collection map[string]ResourceGroup
Collection maps a resource type (e.g. "obfs4") to its corresponding Hashring
func NewCollection ¶
func NewCollection(cfg *CollectionConfig) Collection
NewCollection creates and returns a new resource collection
func (Collection) Add ¶
func (c Collection) Add(resource Resource) error
Add resource to the collection
func (Collection) ApplyDiff ¶
func (c Collection) ApplyDiff(diff *ResourceDiff)
ApplyDiff updates the collection with the resources changed in ResrouceDiff
func (Collection) GetHashring ¶
func (c Collection) GetHashring(partitionName string, rType string) *Hashring
GetHashring returns the hashring of the requested type for the given distributor.
func (Collection) String ¶
func (c Collection) String() string
String returns a summary of the backend resources.
type CollectionConfig ¶
type CollectionConfig struct { // StorageDir is the path to the persistant folder where data will be stored StorageDir string // Types is the list of Resource types that will be stored in the collection Types []TypeConfig }
CollectionConfig holds the configuration to create a Collection
type Dummy ¶
type Dummy struct { ObjectId Hashkey UniqueId Hashkey ExpiryTime time.Duration Distribution string RelationIds []string IPVer IPVersion Blocked LocationSet // contains filtered or unexported fields }
Dummy implements a simple Resource, which we use in unit tests.
func (*Dummy) BlockedIn ¶
func (d *Dummy) BlockedIn() LocationSet
func (*Dummy) SetBlockedIn ¶
func (d *Dummy) SetBlockedIn(LocationSet)
func (*Dummy) SetTest ¶
func (d *Dummy) SetTest(t *ResourceTest)
func (*Dummy) TestResult ¶
func (d *Dummy) TestResult() *ResourceTest
type FilterFunc ¶
FilterFunc takes as input a resource and returns true or false, depending on its filtering criteria.
type Hashring ¶
Hashring represents a hashring consisting of resources.
func (*Hashring) Add ¶
Add adds the given resource to the hashring. If the resource is already present, we update its timestamp and return an error.
func (*Hashring) AddOrUpdate ¶
AddOrUpdate attempts to add the given resource to the hashring. If it already is in the hashring, we update it if (and only if) its object ID changed.
func (*Hashring) ApplyDiff ¶
func (h *Hashring) ApplyDiff(d *ResourceDiff)
ApplyDiff applies the given ResourceDiff to the hashring. New resources are added, changed resources are updated, and gone resources are removed.
func (*Hashring) Filter ¶
func (h *Hashring) Filter(f FilterFunc) []Resource
Filter filters the resources of this hashring with the given filter function and returns the remaining resources as another hashring.
func (*Hashring) Get ¶
Get attempts to retrieve the element identified by the given hash key. If the hashring is empty, an error is returned. If there is no exact match for the given hash key, we return the element whose hash key is the closest to the given hash key in descending direction.
func (*Hashring) GetAll ¶
GetAll returns all of the hashring's resources.
func (*Hashring) GetExact ¶
GetExact attempts to retrieve the element identified by the given hash key. If we cannot find the element, an error is returned.
func (*Hashring) GetMany ¶
func (h *Hashring) GetMany(k Hashkey, num int, req *BridgeRequest) (resources []Resource, err error)
GetMany behaves like Get with the exception that it attempts to return the given number of elements. If the number of desired elements exceeds the number of elements in the hashring all the resources in the hashring will be returned.
func (*Hashring) Len ¶
Len implements the sort interface. This function is unsafe and needs a mutex lock before being used
func (*Hashring) Less ¶
Less implements the sort interface. This function is unsafe and needs a mutex lock before being used
func (*Hashring) Prune ¶
Prune prunes and returns expired resources from the hashring.
func (*Hashring) Remove ¶
Remove removes the given resource from the hashring. If the hashring is empty or we cannot find the key, an error is returned.
type Location ¶
type Location struct { CountryCode string // ISO 3166-1 alpha-2 country code, e.g. "AR". ASN uint32 // Autonomous system number, e.g. 1234. }
Location represents the physical and topological location of a resource or requester.
type LocationSet ¶
LocationSet maps the string representation of locations (because we cannot use structs as map keys) to 'true'.
func (LocationSet) HasLocationsNotIn ¶
func (s1 LocationSet) HasLocationsNotIn(s2 LocationSet) bool
HasLocationsNotIn returns true if s1 contains at least one location that is not in s2.
func (LocationSet) String ¶
func (l LocationSet) String() string
String returns a string representation of the given location set.
type Resource ¶
type Resource interface { Type() string String() string IsValid() bool BlockedIn() LocationSet SetBlockedIn(LocationSet) // Uid returns the resource's unique identifier. Bridges with different // fingerprints have different unique identifiers. Uid() Hashkey // Oid returns the resource's object identifier. Bridges with the *same* // fingerprint but different, say, IP addresses have different object // identifiers. If two resources have the same Oid, they must have the // same Uid but not vice versa. Oid() Hashkey // RelationIdentifiers retrunrs a list of identifiers that represent a // relation between resources. For example the fingerprint, two resources // with the same fingerprint are related to eachother. RelationIdentifiers() []string Test() TestResult() *ResourceTest // Expiry returns the duration after which the resource should be deleted // from the backend (if the backend hasn't received an update). Expiry() time.Duration // Distributor set for this resource Distributor() string // IPVersion() returns IPv4 or IPv6 if the resource IP is not dummy otherwise IPAny IPVersion() IPVersion }
Resource specifies the resources that rdsys hands out to users. This could be a vanilla Tor bridge, and obfs4 bridge, a Snowflake proxy, and even Tor Browser links. Your imagination is the limit.
type ResourceBase ¶
type ResourceBase struct { RType string `json:"type"` RBlockedIn LocationSet `json:"blocked_in"` Location *Location Test *ResourceTest `json:"test_result"` }
ResourceBase provides a data structure plus associated methods that are shared across all of our resources.
func NewResourceBase ¶
func NewResourceBase() *ResourceBase
NewResourceBase returns a new ResourceBase.
func (*ResourceBase) BlockedIn ¶
func (r *ResourceBase) BlockedIn() LocationSet
BlockedIn returns the set of locations that block the resource.
func (*ResourceBase) SetBlockedIn ¶
func (r *ResourceBase) SetBlockedIn(l LocationSet)
SetBlockedIn adds the given location set to the set of locations that block the resource.
func (*ResourceBase) SetType ¶
func (r *ResourceBase) SetType(Type string)
SetType sets the resource's type to the given type.
func (*ResourceBase) TestResult ¶
func (r *ResourceBase) TestResult() *ResourceTest
TestResult returns the resource's test result.
type ResourceDiff ¶
type ResourceDiff struct { New ResourceMap `json:"new"` Changed ResourceMap `json:"changed"` Gone ResourceMap `json:"gone"` // FullUpdate indicates that this diff contains the full list of // resources on the New field. FullUpdate bool `json:"full_update"` }
ResourceDiff represents a diff that contains new, changed, and gone resources. A resource diff can be applied onto data structures that implement a collection of resources, e.g. a Hashring.
func NewResourceDiff ¶
func NewResourceDiff() *ResourceDiff
NewResourceDiff returns a new ResourceDiff.
func (*ResourceDiff) String ¶
func (m *ResourceDiff) String() string
String returns a string representation of ResourceDiff.
type ResourceDiffRecipient ¶
type ResourceDiffRecipient struct { Chan chan *ResourceDiff Request *ResourceRequest }
ResourceDiffRecipient represents the recipient of a resource event, i.e. a distributor; or rather, what we need to send updates to said distributor.
type ResourceGroup ¶
type ResourceGroup interface { Add(resource Resource) error AddOrUpdate(resource Resource) int Remove(resource Resource) error Len() int Clear() Filter(FilterFunc) []Resource GetAll() []Resource Prune() []Resource // contains filtered or unexported methods }
ResourceGroup is a type that holds a list of resources like a Hashring
type ResourceMap ¶
type ResourceMap map[string]ResourceQueue
ResourceMap maps a resource type to a slice of respective resources
func (ResourceMap) ApplyDiff ¶
func (m ResourceMap) ApplyDiff(d *ResourceDiff)
ApplyDiff applies the given ResourceDiff to the ResourceMap. New resources are added, changed resources are updated, and gone resources are removed.
func (ResourceMap) String ¶
func (m ResourceMap) String() string
String returns a string representation of the resource map that's easy on the eyes.
type ResourceQueue ¶
type ResourceQueue []Resource
ResourceQueue implements a queue of resources.
func (*ResourceQueue) Delete ¶
func (q *ResourceQueue) Delete(r1 Resource) error
Delete removes the resource from the queue. If the queue is empty, the function returns an error.
func (*ResourceQueue) Dequeue ¶
func (q *ResourceQueue) Dequeue() (Resource, error)
Dequeue return and removes the oldest resource in the queue. If the queue is empty, the function returns an error.
func (*ResourceQueue) Enqueue ¶
func (q *ResourceQueue) Enqueue(r1 Resource) error
Enqueue adds a resource to the queue. The function returns an error if the resource already exists in the queue.
func (*ResourceQueue) Search ¶
func (q *ResourceQueue) Search(key Hashkey) (Resource, error)
Search searches the resource queue for the given unique ID and either returns the resource it found, or an error if the resource could not be found.
func (*ResourceQueue) Update ¶
func (q *ResourceQueue) Update(r1 Resource) error
Update updates an existing resource if its unique ID matches the unique ID of the given resource. If the queue is empty, the function returns an error.
type ResourceRequest ¶
type ResourceRequest struct { // Name of requesting distributor. RequestOrigin string `json:"request_origin"` ResourceTypes []string `json:"resource_types"` IPVersion IPVersion `json:"ip-version"` Receiver chan *ResourceDiff `json:"-"` }
ResourceRequest represents a request for resources. Distributors use ResourceRequest to request resources from the backend.
func (*ResourceRequest) HasResourceIP ¶
func (r *ResourceRequest) HasResourceIP(ipVersion IPVersion) bool
HasResourceIP returns true if the resource request contains the given IPVersion.
func (*ResourceRequest) HasResourceType ¶
func (r *ResourceRequest) HasResourceType(rType1 string) bool
HasResourceType returns true if the resource request contains the given resource type.
type ResourceState ¶
type ResourceTest ¶
type ResourceTest struct { State int `json:"-"` Speed int `json:"-"` Ratio *float64 `json:"-"` LastTested time.Time `json:"-"` LastWorking time.Time `json:"last_working"` Error string `json:"-"` }
ResourceTest represents the result of a test of a resource. We use the tool bridgestrap for testing if the bridge is functional: https://gitlab.torproject.org/tpo/anti-censorship/bridgestrap And onbasca to test it's speed ratio: https://gitlab.torproject.org/tpo/network-health/onbasca/
type TypeConfig ¶
type TypeConfig struct { // Type name of the Resources Type string // NewResource is a function that retourns a new resource of the Type NewResource func() Resource // Unpartitioned if the resource hosted in a single Hashring or in a partitioned one Unpartitioned bool // Proportions is used for partitioned hashrings and indicates the names // of each partition and it's proportion of resources that should be asigned to it Proportions map[string]int // Stored indicates if the resources of this type should be persistant stored in StoreDir Stored bool }
TypeConfig holds the configuration of one Resource type