rename local variables acn; Add bootstrap status support to ACN/torprovider

This commit is contained in:
Dan Ballard 2018-11-21 22:15:35 -08:00
parent b8a7cd702a
commit 38cff4212d
9 changed files with 90 additions and 28 deletions

View File

@ -23,15 +23,15 @@ type RicochetApplication struct {
v3identity identity.Identity v3identity identity.Identity
name string name string
ls connectivity.ListenService ls connectivity.ListenService
mn connectivity.ACN acn connectivity.ACN
instances []*ApplicationInstance instances []*ApplicationInstance
lock sync.Mutex lock sync.Mutex
aif ApplicationInstanceFactory aif ApplicationInstanceFactory
} }
// Init initializes the underlying RicochetApplication datastructure, making it ready for use // Init initializes the underlying RicochetApplication datastructure, making it ready for use
func (ra *RicochetApplication) Init(mn connectivity.ACN, name string, v3identity identity.Identity, af ApplicationInstanceFactory, cm ContactManagerInterface) { func (ra *RicochetApplication) Init(acn connectivity.ACN, name string, v3identity identity.Identity, af ApplicationInstanceFactory, cm ContactManagerInterface) {
ra.mn = mn ra.acn = acn
ra.name = name ra.name = name
ra.v3identity = v3identity ra.v3identity = v3identity
ra.aif = af ra.aif = af
@ -84,7 +84,7 @@ func (ra *RicochetApplication) HandleApplicationInstance(rai *ApplicationInstanc
// Open a connection to another Ricochet peer at onionAddress. If they are unknown to use, use requestMessage (otherwise can be blank) // Open a connection to another Ricochet peer at onionAddress. If they are unknown to use, use requestMessage (otherwise can be blank)
func (ra *RicochetApplication) Open(onionAddress string, requestMessage string) (*ApplicationInstance, error) { func (ra *RicochetApplication) Open(onionAddress string, requestMessage string) (*ApplicationInstance, error) {
rc, err := goricochet.Open(ra.mn, onionAddress) rc, err := goricochet.Open(ra.acn, onionAddress)
rc.TraceLog(true) rc.TraceLog(true)
if err != nil { if err != nil {
log.Printf("Error in application.Open(): %v\n", err) log.Printf("Error in application.Open(): %v\n", err)

View File

@ -70,13 +70,13 @@ func main() {
echobot := new(application.RicochetApplication) echobot := new(application.RicochetApplication)
cpubk, cprivk, err := ed25519.GenerateKey(rand.Reader) cpubk, cprivk, err := ed25519.GenerateKey(rand.Reader)
mn, err := connectivity.StartTor(".", "") acn, err := connectivity.StartTor(".", "")
if err != nil { if err != nil {
log.Panicf("Unable to start Tor: %v", err) log.Panicf("Unable to start Tor: %v", err)
} }
defer mn.Close() defer acn.Close()
listenService, err := mn.Listen(cprivk, application.RicochetPort) listenService, err := acn.Listen(cprivk, application.RicochetPort)
if err != nil { if err != nil {
log.Fatalf("error setting up onion service: %v", err) log.Fatalf("error setting up onion service: %v", err)
@ -94,7 +94,7 @@ func main() {
} }
}) })
echobot.Init(mn, "echobot", identity.InitializeV3("echobot", &cprivk, &cpubk), af, new(application.AcceptAllContactManager)) echobot.Init(acn, "echobot", identity.InitializeV3("echobot", &cprivk, &cpubk), af, new(application.AcceptAllContactManager))
log.Printf("echobot listening on %s", listenService.AddressFull()) log.Printf("echobot listening on %s", listenService.AddressFull())
go echobot.Run(listenService) go echobot.Run(listenService)
@ -106,7 +106,7 @@ func main() {
//////////// ////////////
//alicebot should nominally be in another package to prevent initializing it directly //alicebot should nominally be in another package to prevent initializing it directly
alice := NewAliceBot(mn, listenService.AddressIdentity()) alice := NewAliceBot(acn, listenService.AddressIdentity())
alice.SendMessage("be gay") alice.SendMessage("be gay")
alice.SendMessage("do crime") alice.SendMessage("do crime")
@ -114,7 +114,7 @@ func main() {
time.Sleep(time.Second * 30) time.Sleep(time.Second * 30)
} }
func NewAliceBot(mn connectivity.ACN, onion string) alicebot { func NewAliceBot(acn connectivity.ACN, onion string) alicebot {
alice := alicebot{} alice := alicebot{}
alice.messages = make(map[uint32]string) alice.messages = make(map[uint32]string)
@ -124,7 +124,7 @@ func NewAliceBot(mn connectivity.ACN, onion string) alicebot {
log.Fatalf("[alice] error generating key: %v", err) log.Fatalf("[alice] error generating key: %v", err)
} }
rc, err := goricochet.Open(mn, onion) rc, err := goricochet.Open(acn, onion)
if err != nil { if err != nil {
log.Fatalf("[alice] error connecting to echobot: %v", err) log.Fatalf("[alice] error connecting to echobot: %v", err)
} }

View File

@ -21,6 +21,11 @@ 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() (int, string)
// WaitTillBootstrapped Blocks until underlying network is bootstrapped
WaitTillBootstrapped()
// Open takes a hostname and returns a net.Conn to the derived endpoint // Open takes a hostname and returns a net.Conn to the derived endpoint
// Open allows a client to resolve various hostnames to connections // Open allows a client to resolve various hostnames to connections
// The supported types are onions address are: // The supported types are onions address are:

View File

@ -29,6 +29,15 @@ func (ls *localListenService) Close() {
ls.l.Close() ls.l.Close()
} }
// GetBootstrapStatus returns an int 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
func (lp *localProvider) GetBootstrapStatus() (int, string) {
return 100, "Done"
}
// WaitTillBootstrapped Blocks until underlying network is bootstrapped
func (lp *localProvider) WaitTillBootstrapped() {
}
func (lp *localProvider) Listen(identity PrivateKey, port int) (ListenService, error) { func (lp *localProvider) Listen(identity PrivateKey, port int) (ListenService, error) {
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%v", port)) l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%v", port))
return &localListenService{l}, err return &localListenService{l}, err

View File

@ -15,6 +15,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time"
) )
const ( const (
@ -51,6 +52,41 @@ func (ols *onionListenService) Close() {
ols.os.Close() ols.os.Close()
} }
// GetBootstrapStatus returns an int 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
func (tp *torProvider) GetBootstrapStatus() (int, string) {
kvs, err := tp.t.Control.GetInfo("status/bootstrap-phase")
if err != nil {
return 0, "error"
}
progress := 0
status := ""
if len(kvs) > 0 {
progRe := regexp.MustCompile("PROGRESS=([0-9]*)")
sumRe := regexp.MustCompile("SUMMARY=\"(.*)\"$")
if progMatches := progRe.FindStringSubmatch(kvs[0].Val); len(progMatches) > 1 {
progress, _ = strconv.Atoi(progMatches[1])
}
if statusMatches := sumRe.FindStringSubmatch(kvs[0].Val); len(statusMatches) > 1 {
status = statusMatches[1]
}
}
return progress, status
}
// WaitTillBootstrapped Blocks until underlying network is bootstrapped
func (tp *torProvider) WaitTillBootstrapped() {
for true {
progress, _ := tp.GetBootstrapStatus()
if progress == 100 {
break
}
time.Sleep(100 * time.Millisecond)
}
}
func (tp *torProvider) Listen(identity PrivateKey, port int) (ListenService, error) { func (tp *torProvider) Listen(identity PrivateKey, port int) (ListenService, error) {
tp.lock.Lock() tp.lock.Lock()
defer tp.lock.Unlock() defer tp.lock.Unlock()

View File

@ -1,12 +1,24 @@
package connectivity package connectivity
import "testing" import (
"fmt"
"testing"
"time"
)
func TestTorProvider(t *testing.T) { func TestTorProvider(t *testing.T) {
m, err := StartTor(".", "") acn, err := StartTor(".", "")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
m.Close() progress := 0
status := ""
for progress < 100 {
progress, status = acn.GetBootstrapStatus()
fmt.Printf("%v %v\n", progress, status)
time.Sleep(100)
}
acn.Close()
} }

View File

@ -13,8 +13,8 @@ import (
// will be closed. This function blocks until version negotiation has completed. // will be closed. This function blocks until version negotiation has completed.
// The application should call Process() on the returned OpenConnection to continue // The application should call Process() on the returned OpenConnection to continue
// handling protocol messages. // handling protocol messages.
func Open(mn connectivity.ACN, remoteHostname string) (*connection.Connection, error) { func Open(acn connectivity.ACN, remoteHostname string) (*connection.Connection, error) {
conn, remoteHostname, err := mn.Open(remoteHostname) conn, remoteHostname, err := acn.Open(remoteHostname)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -19,12 +19,12 @@ func SimpleServer() {
} }
func TestRicochetOpen(t *testing.T) { func TestRicochetOpen(t *testing.T) {
mn := connectivity.LocalProvider() acn := connectivity.LocalProvider()
go SimpleServer() go SimpleServer()
// Wait for Server to Initialize // Wait for Server to Initialize
time.Sleep(time.Second) time.Sleep(time.Second)
rc, err := Open(mn, "127.0.0.1:11000|abcdefghijklmno.onion") rc, err := Open(acn, "127.0.0.1:11000|abcdefghijklmno.onion")
if err == nil { if err == nil {
if rc.IsInbound { if rc.IsInbound {
t.Errorf("RicochetConnection declares itself as an Inbound connection after an Outbound attempt...that shouldn't happen") t.Errorf("RicochetConnection declares itself as an Inbound connection after an Outbound attempt...that shouldn't happen")
@ -46,19 +46,19 @@ func BadServer() {
} }
func TestRicochetOpenWithError(t *testing.T) { func TestRicochetOpenWithError(t *testing.T) {
mn := connectivity.LocalProvider() acn := connectivity.LocalProvider()
go BadServer() go BadServer()
// Wait for Server to Initialize // Wait for Server to Initialize
time.Sleep(time.Second) time.Sleep(time.Second)
_, err := Open(mn, "127.0.0.1:11001|abcdefghijklmno.onion") _, err := Open(acn, "127.0.0.1:11001|abcdefghijklmno.onion")
if err == nil { if err == nil {
t.Errorf("Open should have failed because of bad version negotiation.") t.Errorf("Open should have failed because of bad version negotiation.")
} }
} }
func TestRicochetOpenWithNoServer(t *testing.T) { func TestRicochetOpenWithNoServer(t *testing.T) {
mn := connectivity.LocalProvider() acn := connectivity.LocalProvider()
_, err := Open(mn, "127.0.0.1:11002|abcdefghijklmno.onion") _, err := Open(acn, "127.0.0.1:11002|abcdefghijklmno.onion")
if err == nil { if err == nil {
t.Errorf("Open should have failed because of bad version negotiation.") t.Errorf("Open should have failed because of bad version negotiation.")
} }

View File

@ -98,7 +98,7 @@ func (bot *ChatEchoBot) ChatMessageAck(messageID uint32, accepted bool) {
} }
func TestApplicationIntegration(t *testing.T) { func TestApplicationIntegration(t *testing.T) {
mn, err := connectivity.StartTor(".", "") acn, err := connectivity.StartTor(".", "")
if err != nil { if err != nil {
t.Fatalf("Could not start tor: %v", err) t.Fatalf("Could not start tor: %v", err)
} }
@ -124,7 +124,7 @@ func TestApplicationIntegration(t *testing.T) {
apubk, apk, _ := utils.GeneratePrivateKeyV3() apubk, apk, _ := utils.GeneratePrivateKeyV3()
aliceAddr := utils.GetTorV3Hostname(apubk) aliceAddr := utils.GetTorV3Hostname(apubk)
fmt.Println("Seting up alice's onion " + aliceAddr + "...") fmt.Println("Seting up alice's onion " + aliceAddr + "...")
al, err := mn.Listen(apk, application.RicochetPort) al, err := acn.Listen(apk, application.RicochetPort)
if err != nil { if err != nil {
t.Fatalf("Could not setup Onion for Alice: %v", err) t.Fatalf("Could not setup Onion for Alice: %v", err)
} }
@ -137,7 +137,7 @@ func TestApplicationIntegration(t *testing.T) {
return chat return chat
} }
}) })
alice.Init(mn, "Alice", identity.InitializeV3("Alice", &apk, &apubk), af, new(application.AcceptAllContactManager)) alice.Init(acn, "Alice", identity.InitializeV3("Alice", &apk, &apubk), af, new(application.AcceptAllContactManager))
fmt.Println("Running alice...") fmt.Println("Running alice...")
go alice.Run(al) go alice.Run(al)
@ -149,7 +149,7 @@ func TestApplicationIntegration(t *testing.T) {
} }
bobAddr := utils.GetTorV3Hostname(bpubk) bobAddr := utils.GetTorV3Hostname(bpubk)
fmt.Println("Seting up bob's onion " + bobAddr + "...") fmt.Println("Seting up bob's onion " + bobAddr + "...")
bl, _ := mn.Listen(bpk, application.RicochetPort) bl, _ := acn.Listen(bpk, application.RicochetPort)
af.AddHandler("im.ricochet.chat", func(rai *application.ApplicationInstance) func() channels.Handler { af.AddHandler("im.ricochet.chat", func(rai *application.ApplicationInstance) func() channels.Handler {
return func() channels.Handler { return func() channels.Handler {
chat := new(channels.ChatChannel) chat := new(channels.ChatChannel)
@ -157,7 +157,7 @@ func TestApplicationIntegration(t *testing.T) {
return chat return chat
} }
}) })
bob.Init(mn, "Bob", identity.InitializeV3("Bob", &bpk, &bpubk), af, new(application.AcceptAllContactManager)) bob.Init(acn, "Bob", identity.InitializeV3("Bob", &bpk, &bpubk), af, new(application.AcceptAllContactManager))
go bob.Run(bl) go bob.Run(bl)
fmt.Println("Waiting for alice and bob hidden services to percolate...") fmt.Println("Waiting for alice and bob hidden services to percolate...")
@ -209,7 +209,7 @@ func TestApplicationIntegration(t *testing.T) {
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
fmt.Println("Shutting down bine/tor") fmt.Println("Shutting down bine/tor")
mn.Close() acn.Close()
finalGoRoutines := runtime.NumGoroutine() finalGoRoutines := runtime.NumGoroutine()