torProvider now also consults network-liveness
This commit is contained in:
parent
beb2665c49
commit
35293ea087
4
acn.go
4
acn.go
|
@ -34,10 +34,12 @@ type ListenService interface {
|
||||||
// ACN is Anonymous Communication Network implementation wrapper that supports Open for new connections and Listen to accept connections
|
// ACN is Anonymous Communication Network implementation wrapper that supports Open for new connections and Listen to accept connections
|
||||||
type ACN interface {
|
type ACN interface {
|
||||||
// GetBootstrapStatus returns an int 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
|
// GetBootstrapStatus returns an int 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
|
||||||
|
// On Network down it returns -1
|
||||||
|
// On ACN error state it returns -2
|
||||||
GetBootstrapStatus() (int, string)
|
GetBootstrapStatus() (int, string)
|
||||||
// WaitTillBootstrapped Blocks until underlying network is bootstrapped
|
// WaitTillBootstrapped Blocks until underlying network is bootstrapped
|
||||||
WaitTillBootstrapped()
|
WaitTillBootstrapped()
|
||||||
// Sets the calback function to be called when ACN status changes
|
// Sets the callback function to be called when ACN status changes
|
||||||
SetStatusCallback(callback func(int, string))
|
SetStatusCallback(callback func(int, string))
|
||||||
|
|
||||||
// Restarts the underlying connection
|
// Restarts the underlying connection
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
const (
|
const (
|
||||||
minStatusIntervalMs = 200
|
minStatusIntervalMs = 200
|
||||||
maxStatusIntervalMs = 2000
|
maxStatusIntervalMs = 2000
|
||||||
|
restartCooldown = time.Second * 30
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -33,6 +34,12 @@ const (
|
||||||
CannotDialRicochetAddressError = connectivity.Error("CannotDialRicochetAddressError")
|
CannotDialRicochetAddressError = connectivity.Error("CannotDialRicochetAddressError")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
networkUnknown int = iota
|
||||||
|
networkDown
|
||||||
|
networkUp
|
||||||
|
)
|
||||||
|
|
||||||
type onionListenService struct {
|
type onionListenService struct {
|
||||||
os *tor.OnionService
|
os *tor.OnionService
|
||||||
tp *torProvider
|
tp *torProvider
|
||||||
|
@ -47,6 +54,7 @@ type torProvider struct {
|
||||||
breakChan chan bool
|
breakChan chan bool
|
||||||
childListeners map[string]*onionListenService
|
childListeners map[string]*onionListenService
|
||||||
statusCallback func(int, string)
|
statusCallback func(int, string)
|
||||||
|
lastRestartTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ols *onionListenService) AddressFull() string {
|
func (ols *onionListenService) AddressFull() string {
|
||||||
|
@ -66,14 +74,22 @@ func (ols *onionListenService) Close() {
|
||||||
ols.os.Close()
|
ols.os.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBootstrapStatus returns an int -1 on error or 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
|
// GetBootstrapStatus returns an int 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
|
||||||
|
// returns -1 on network disconnected
|
||||||
|
// returns -2 on error
|
||||||
func (tp *torProvider) GetBootstrapStatus() (int, string) {
|
func (tp *torProvider) GetBootstrapStatus() (int, string) {
|
||||||
if tp.t == nil {
|
if tp.t == nil {
|
||||||
return -1, "error: no tor, trying to restart..."
|
return -2, "error: no tor, trying to restart..."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netStatus := tp.getNetworkStatus()
|
||||||
|
if netStatus == networkDown {
|
||||||
|
return -1, "Network Down"
|
||||||
|
}
|
||||||
|
|
||||||
kvs, err := tp.t.Control.GetInfo("status/bootstrap-phase")
|
kvs, err := tp.t.Control.GetInfo("status/bootstrap-phase")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, "error"
|
return -2, "error querrying status/bootstrap-phase"
|
||||||
}
|
}
|
||||||
progress := 0
|
progress := 0
|
||||||
status := ""
|
status := ""
|
||||||
|
@ -104,6 +120,21 @@ func (tp *torProvider) WaitTillBootstrapped() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getNetworkStatus returns tor's beleif in the underlying network's status
|
||||||
|
func (tp *torProvider) getNetworkStatus() int {
|
||||||
|
if tp.t == nil {
|
||||||
|
return networkDown
|
||||||
|
}
|
||||||
|
val, err := tp.t.Control.GetInfo("network-liveness")
|
||||||
|
if err != nil {
|
||||||
|
return networkDown
|
||||||
|
}
|
||||||
|
if val[0].Val == "up" {
|
||||||
|
return networkUp
|
||||||
|
}
|
||||||
|
return networkDown
|
||||||
|
}
|
||||||
|
|
||||||
func (tp *torProvider) Listen(identity connectivity.PrivateKey, port int) (connectivity.ListenService, error) {
|
func (tp *torProvider) Listen(identity connectivity.PrivateKey, port int) (connectivity.ListenService, error) {
|
||||||
var onion = ""
|
var onion = ""
|
||||||
var privkey ed25519.PrivateKey
|
var privkey ed25519.PrivateKey
|
||||||
|
@ -154,9 +185,7 @@ func (tp *torProvider) Listen(identity connectivity.PrivateKey, port int) (conne
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tp *torProvider) Restart() {
|
func (tp *torProvider) Restart() {
|
||||||
if tp.statusCallback != nil {
|
tp.callStatusCallback(0, "rebooting")
|
||||||
tp.statusCallback(0, "rebooting")
|
|
||||||
}
|
|
||||||
tp.restart()
|
tp.restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +228,14 @@ func (tp *torProvider) SetStatusCallback(callback func(int, string)) {
|
||||||
tp.statusCallback = callback
|
tp.statusCallback = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tp *torProvider) callStatusCallback(prog int, status string) {
|
||||||
|
tp.lock.Lock()
|
||||||
|
if tp.statusCallback != nil {
|
||||||
|
tp.statusCallback(prog, status)
|
||||||
|
}
|
||||||
|
tp.lock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// NewTorACN creates/starts a Tor ACN and returns a usable ACN object
|
// NewTorACN creates/starts a Tor ACN and returns a usable ACN object
|
||||||
func NewTorACN(appDirectory string, bundledTorPath string) (connectivity.ACN, error) {
|
func NewTorACN(appDirectory string, bundledTorPath string) (connectivity.ACN, error) {
|
||||||
tp, err := startTor(appDirectory, bundledTorPath)
|
tp, err := startTor(appDirectory, bundledTorPath)
|
||||||
|
@ -225,7 +262,7 @@ func newHideCmd(exePath string) process.Creator {
|
||||||
func startTor(appDirectory string, bundledTorPath string) (*torProvider, error) {
|
func startTor(appDirectory string, bundledTorPath string) (*torProvider, error) {
|
||||||
dataDir := path.Join(appDirectory, "tor")
|
dataDir := path.Join(appDirectory, "tor")
|
||||||
os.MkdirAll(dataDir, 0700)
|
os.MkdirAll(dataDir, 0700)
|
||||||
tp := &torProvider{appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool), statusCallback: nil}
|
tp := &torProvider{appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool), statusCallback: nil, lastRestartTime: time.Now()}
|
||||||
|
|
||||||
// attempt connect to system tor
|
// attempt connect to system tor
|
||||||
log.Debugf("dialing system tor control port\n")
|
log.Debugf("dialing system tor control port\n")
|
||||||
|
@ -277,34 +314,38 @@ func (tp *torProvider) unregisterListener(id string) {
|
||||||
|
|
||||||
func (tp *torProvider) monitorRestart() {
|
func (tp *torProvider) monitorRestart() {
|
||||||
lastBootstrapProgress := 0
|
lastBootstrapProgress := 0
|
||||||
|
lastNetworkStatus := networkUnknown
|
||||||
interval := minStatusIntervalMs
|
interval := minStatusIntervalMs
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Millisecond * time.Duration(interval)):
|
case <-time.After(time.Millisecond * time.Duration(interval)):
|
||||||
prog, status := tp.GetBootstrapStatus()
|
if interval < maxStatusIntervalMs {
|
||||||
|
interval *= 2
|
||||||
if prog == -1 && tp.t != nil {
|
|
||||||
tp.lock.Lock()
|
|
||||||
if tp.statusCallback != nil {
|
|
||||||
tp.statusCallback(prog, status)
|
|
||||||
}
|
|
||||||
tp.lock.Unlock()
|
|
||||||
tp.restart()
|
|
||||||
interval = minStatusIntervalMs
|
|
||||||
} else if prog != lastBootstrapProgress {
|
|
||||||
tp.lock.Lock()
|
|
||||||
if tp.statusCallback != nil {
|
|
||||||
tp.statusCallback(prog, status)
|
|
||||||
}
|
|
||||||
tp.lock.Unlock()
|
|
||||||
interval = minStatusIntervalMs
|
|
||||||
} else {
|
|
||||||
if interval < maxStatusIntervalMs {
|
|
||||||
interval *= 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lastBootstrapProgress = prog
|
|
||||||
|
netStatus := tp.getNetworkStatus()
|
||||||
|
if netStatus == networkDown {
|
||||||
|
if lastNetworkStatus != netStatus {
|
||||||
|
tp.callStatusCallback(-1, "Network Down")
|
||||||
|
}
|
||||||
|
lastBootstrapProgress = 0
|
||||||
|
lastNetworkStatus = netStatus
|
||||||
|
} else {
|
||||||
|
lastNetworkStatus = networkUp
|
||||||
|
prog, status := tp.GetBootstrapStatus()
|
||||||
|
if prog == -1 && tp.t != nil {
|
||||||
|
tp.callStatusCallback(-2, status)
|
||||||
|
log.Infof("monitorRestart calling tp.restart() with prog:%v\n", prog)
|
||||||
|
tp.restart()
|
||||||
|
interval = minStatusIntervalMs
|
||||||
|
} else if prog != lastBootstrapProgress {
|
||||||
|
tp.callStatusCallback(prog, status)
|
||||||
|
interval = minStatusIntervalMs
|
||||||
|
}
|
||||||
|
lastBootstrapProgress = prog
|
||||||
|
}
|
||||||
|
|
||||||
case <-tp.breakChan:
|
case <-tp.breakChan:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -312,13 +353,17 @@ func (tp *torProvider) monitorRestart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tp *torProvider) restart() {
|
func (tp *torProvider) restart() {
|
||||||
|
|
||||||
for _, child := range tp.childListeners {
|
|
||||||
child.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
tp.lock.Lock()
|
tp.lock.Lock()
|
||||||
defer tp.lock.Unlock()
|
defer tp.lock.Unlock()
|
||||||
|
if time.Now().Sub(tp.lastRestartTime) < restartCooldown {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tp.lastRestartTime = time.Now()
|
||||||
|
|
||||||
|
for _, child := range tp.childListeners {
|
||||||
|
delete(tp.childListeners, child.AddressIdentity())
|
||||||
|
child.os.Close()
|
||||||
|
}
|
||||||
|
|
||||||
tp.t.Close()
|
tp.t.Close()
|
||||||
tp.t = nil
|
tp.t = nil
|
||||||
|
|
Loading…
Reference in New Issue