mirror of
https://github.com/Egida/EndGame0.git
synced 2025-08-02 19:36:03 -04:00
158 lines
4.9 KiB
Go
158 lines
4.9 KiB
Go
package onionbalance
|
|
|
|
import (
|
|
"errors"
|
|
"github.com/sirupsen/logrus"
|
|
"gobalance/pkg/btime"
|
|
"gobalance/pkg/stem/descriptor"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Instance struct {
|
|
controller *Controller
|
|
OnionAddress string
|
|
introSetChangedSincePublished bool
|
|
descriptor *ReceivedDescriptor
|
|
descriptorMtx sync.RWMutex
|
|
IntroSetModifiedTimestamp *time.Time
|
|
}
|
|
|
|
func NewInstance(controller *Controller, onionAddress string) *Instance {
|
|
p := Params()
|
|
i := &Instance{}
|
|
i.controller = controller
|
|
|
|
if onionAddress != "" {
|
|
onionAddress = strings.Replace(onionAddress, ".onion", "", 1)
|
|
}
|
|
i.OnionAddress = onionAddress
|
|
|
|
// Onion address does not contain the '.onion'.
|
|
logrus.Warnf("Loaded instance %s", onionAddress)
|
|
|
|
nInstances := p.NInstances()
|
|
p.SetNInstances(nInstances + 1)
|
|
i.introSetChangedSincePublished = false
|
|
|
|
i.SetDescriptor(nil)
|
|
|
|
// When was the intro set of this instance last modified?
|
|
i.IntroSetModifiedTimestamp = nil
|
|
return i
|
|
}
|
|
|
|
func (i *Instance) SetDescriptor(newDescriptor *ReceivedDescriptor) {
|
|
i.descriptorMtx.Lock()
|
|
defer i.descriptorMtx.Unlock()
|
|
i.descriptor = newDescriptor
|
|
}
|
|
|
|
func (i *Instance) GetDescriptor() *ReceivedDescriptor {
|
|
i.descriptorMtx.RLock()
|
|
defer i.descriptorMtx.RUnlock()
|
|
return i.descriptor
|
|
}
|
|
|
|
// Return True if this instance has this onion address
|
|
func (i *Instance) hasOnionAddress(onionAddress string) bool {
|
|
// Strip the ".onion" part of the address if it exists since some
|
|
// subsystems don't use it (e.g. Tor sometimes omits it from control
|
|
// port responses)
|
|
myOnionAddress := strings.TrimSuffix(i.OnionAddress, ".onion")
|
|
theirOnionAddress := strings.TrimSuffix(onionAddress, ".onion")
|
|
|
|
return myOnionAddress == theirOnionAddress
|
|
}
|
|
|
|
// FetchDescriptor try fetch a fresh descriptor for this service instance from the HSDirs
|
|
func (i *Instance) FetchDescriptor() error {
|
|
logrus.Debugf("Trying to fetch a descriptor for instance %s.onion.", i.OnionAddress)
|
|
return i.controller.GetHiddenServiceDescriptor(i.OnionAddress)
|
|
}
|
|
|
|
var ErrInstanceHasNoDescriptor = errors.New("InstanceHasNoDescriptor")
|
|
var ErrInstanceIsOffline = errors.New("InstanceIsOffline")
|
|
|
|
// GetIntrosForPublish get a list of stem.descriptor.IntroductionPointV3 objects for this descriptor
|
|
// Raise :InstanceHasNoDescriptor: if there is no descriptor for this instance
|
|
// Raise :InstanceIsOffline: if the instance is offline.
|
|
func (i *Instance) GetIntrosForPublish() ([]descriptor.IntroductionPointV3, error) {
|
|
p := Params()
|
|
instDescriptor := i.GetDescriptor()
|
|
if instDescriptor == nil {
|
|
adaptDown := p.AdaptDown()
|
|
p.SetAdaptDown(adaptDown + 1)
|
|
adaptDownNoDescriptor := p.AdaptDownNoDescriptor()
|
|
p.SetAdaptDownNoDescriptor(adaptDownNoDescriptor + 1)
|
|
return nil, ErrInstanceHasNoDescriptor
|
|
}
|
|
if instDescriptor.IsOld() {
|
|
adaptDown := p.AdaptDown()
|
|
p.SetAdaptDown(adaptDown + 1)
|
|
|
|
adaptDownInstanceOld := p.AdaptDownInstanceOld()
|
|
p.SetAdaptDownInstanceOld(adaptDownInstanceOld + 1)
|
|
return nil, ErrInstanceIsOffline
|
|
}
|
|
adaptUp := p.AdaptUp()
|
|
p.SetAdaptUp(adaptUp + 1)
|
|
return instDescriptor.GetIntroPoints(), nil
|
|
}
|
|
|
|
// We received a descriptor (with 'descriptor_text') for 'onion_address'.
|
|
// Register it to this instance.
|
|
func (i *Instance) registerDescriptor(descriptorText, onionAddress string) {
|
|
logrus.Debugf("Found instance %s for this new descriptor!", i.OnionAddress)
|
|
p := Params()
|
|
|
|
if onionAddress != i.OnionAddress {
|
|
panic("onion_address != i.OnionAddress")
|
|
}
|
|
|
|
// Parse descriptor. If it parsed correctly, we know that this
|
|
// descriptor is truly for this instance (since the onion address
|
|
// matches)
|
|
newDescriptor, err := NewReceivedDescriptor(descriptorText, onionAddress)
|
|
if err != nil {
|
|
if err == ErrBadDescriptor {
|
|
logrus.Warningf("Received bad descriptor for %s. Ignoring.", i.OnionAddress)
|
|
return
|
|
}
|
|
panic(err)
|
|
}
|
|
|
|
// Before replacing the current descriptor with this one, check if the
|
|
// introduction point set changed:
|
|
|
|
// If this is the first descriptor for this instance, the intro point set changed
|
|
|
|
if i.GetDescriptor() == nil {
|
|
logrus.Infof("This is the first time we seen a descriptor for instance %s!", i.OnionAddress)
|
|
tmp := btime.Clock.Now().UTC()
|
|
i.IntroSetModifiedTimestamp = &tmp
|
|
i.SetDescriptor(newDescriptor)
|
|
return
|
|
}
|
|
|
|
if i.GetDescriptor() == nil {
|
|
panic("i.descriptor == nil")
|
|
}
|
|
if newDescriptor.introSet.Len() == 0 {
|
|
panic("new_descriptor.introSet.Len() == 0")
|
|
}
|
|
|
|
// We already have a descriptor but this is a new one. Check the intro points!
|
|
if !newDescriptor.introSet.Equals(*i.GetDescriptor().introSet) {
|
|
logrus.Infof("We got a new descriptor for instance %s and the intro set changed!", i.OnionAddress)
|
|
tmp := btime.Clock.Now().UTC()
|
|
i.IntroSetModifiedTimestamp = &tmp
|
|
adaptIntroChanged := p.AdaptIntroChanged()
|
|
p.SetAdaptIntroChanged(adaptIntroChanged + 1)
|
|
} else {
|
|
logrus.Infof("We got a new descriptor for instance %s but the intro set did not change.", i.OnionAddress)
|
|
}
|
|
i.SetDescriptor(newDescriptor)
|
|
|
|
}
|