2019-08-08 18:11:31 +00:00
|
|
|
package testing
|
2019-05-15 19:45:45 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"cwtch.im/tapir"
|
2019-07-16 19:14:42 +00:00
|
|
|
"cwtch.im/tapir/applications"
|
|
|
|
"cwtch.im/tapir/networks/tor"
|
2019-08-08 18:11:31 +00:00
|
|
|
"cwtch.im/tapir/primitives"
|
2019-05-15 19:45:45 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
|
|
|
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
|
|
|
"golang.org/x/crypto/ed25519"
|
2019-08-08 18:11:31 +00:00
|
|
|
"runtime"
|
|
|
|
"sync"
|
|
|
|
"testing"
|
2019-05-15 19:45:45 +00:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2019-05-21 18:28:10 +00:00
|
|
|
// SimpleApp is a trivial implementation of a basic p2p application
|
2019-05-15 19:45:45 +00:00
|
|
|
type SimpleApp struct {
|
2019-07-16 19:14:42 +00:00
|
|
|
applications.AuthApp
|
2019-05-15 19:45:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewInstance should always return a new instantiation of the application.
|
2019-09-14 23:44:19 +00:00
|
|
|
func (ea *SimpleApp) NewInstance() tapir.Application {
|
2019-05-15 19:45:45 +00:00
|
|
|
return new(SimpleApp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init is run when the connection is first started.
|
2019-09-14 23:44:19 +00:00
|
|
|
func (ea *SimpleApp) Init(connection tapir.Connection) {
|
2019-05-15 19:45:45 +00:00
|
|
|
// First run the Authentication App
|
|
|
|
ea.AuthApp.Init(connection)
|
|
|
|
|
2019-07-16 19:14:42 +00:00
|
|
|
if connection.HasCapability(applications.AuthCapability) {
|
2019-05-15 19:45:45 +00:00
|
|
|
// The code for out simple application (We just send and receive "Hello"
|
|
|
|
connection.Send([]byte("Hello"))
|
|
|
|
message := connection.Expect()
|
|
|
|
log.Infof("Received: %q", message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-08 18:11:31 +00:00
|
|
|
var AuthSuccess = false
|
|
|
|
|
2019-07-16 20:22:30 +00:00
|
|
|
// CheckConnection is a simple test that GetConnection is working.
|
2019-08-08 18:11:31 +00:00
|
|
|
func CheckConnection(service tapir.Service, hostname string, group *sync.WaitGroup) {
|
2019-07-16 20:22:30 +00:00
|
|
|
for {
|
|
|
|
_, err := service.GetConnection(hostname)
|
|
|
|
if err == nil {
|
|
|
|
log.Infof("Authed!")
|
2019-08-08 18:11:31 +00:00
|
|
|
group.Done()
|
2019-07-16 20:22:30 +00:00
|
|
|
return
|
|
|
|
}
|
2019-08-08 18:11:31 +00:00
|
|
|
log.Infof("Waiting for Authentication...%v", err)
|
|
|
|
time.Sleep(time.Second * 5)
|
2019-07-16 20:22:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-08 18:11:31 +00:00
|
|
|
func TestTapir(t *testing.T) {
|
2019-05-15 19:45:45 +00:00
|
|
|
|
2019-08-08 18:11:31 +00:00
|
|
|
numRoutinesStart := runtime.NumGoroutine()
|
2019-05-15 19:45:45 +00:00
|
|
|
log.SetLevel(log.LevelDebug)
|
2019-08-08 18:11:31 +00:00
|
|
|
log.Infof("Number of goroutines open at start: %d", runtime.NumGoroutine())
|
2019-05-15 19:45:45 +00:00
|
|
|
// Connect to Tor
|
|
|
|
var acn connectivity.ACN
|
|
|
|
acn, _ = connectivity.StartTor("./", "")
|
|
|
|
acn.WaitTillBootstrapped()
|
|
|
|
|
|
|
|
// Generate Server Keys
|
2019-08-08 19:07:13 +00:00
|
|
|
id, sk := primitives.InitializeEphemeralIdentity()
|
2019-05-15 19:45:45 +00:00
|
|
|
|
2019-06-05 18:44:26 +00:00
|
|
|
// Init the Server running the Simple App.
|
2019-05-15 19:45:45 +00:00
|
|
|
var service tapir.Service
|
2019-07-16 19:14:42 +00:00
|
|
|
service = new(tor.BaseOnionService)
|
2019-08-08 18:11:31 +00:00
|
|
|
service.Init(acn, sk, &id)
|
|
|
|
|
|
|
|
// Goroutine Management
|
|
|
|
sg := new(sync.WaitGroup)
|
|
|
|
sg.Add(1)
|
|
|
|
go func() {
|
2019-09-14 23:44:19 +00:00
|
|
|
service.Listen(new(SimpleApp))
|
2019-08-08 18:11:31 +00:00
|
|
|
sg.Done()
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Wait for server to come online
|
|
|
|
time.Sleep(time.Second * 30)
|
|
|
|
wg := new(sync.WaitGroup)
|
|
|
|
wg.Add(2)
|
|
|
|
// Init a Client to Connect to the Server
|
|
|
|
client, clienthostname := genclient(acn)
|
|
|
|
go connectclient(client, id.PublicKey(), wg)
|
|
|
|
CheckConnection(service, clienthostname, wg)
|
|
|
|
wg.Wait()
|
|
|
|
// Wait for Server to Sync
|
|
|
|
time.Sleep(time.Second * 2)
|
|
|
|
log.Infof("Closing ACN...")
|
|
|
|
acn.Close()
|
|
|
|
sg.Wait()
|
|
|
|
time.Sleep(time.Second * 2)
|
|
|
|
log.Infof("Number of goroutines open at close: %d", runtime.NumGoroutine())
|
|
|
|
if numRoutinesStart != runtime.NumGoroutine() {
|
|
|
|
t.Errorf("Potential goroutine leak: Num Start:%v NumEnd: %v", numRoutinesStart, runtime.NumGoroutine())
|
|
|
|
}
|
|
|
|
if !AuthSuccess {
|
|
|
|
t.Fatalf("Integration Test FAILED, client did not auth with server")
|
|
|
|
}
|
2019-05-15 19:45:45 +00:00
|
|
|
}
|
|
|
|
|
2019-07-16 20:22:30 +00:00
|
|
|
func genclient(acn connectivity.ACN) (tapir.Service, string) {
|
2019-08-08 19:07:13 +00:00
|
|
|
id, sk := primitives.InitializeEphemeralIdentity()
|
2019-05-15 19:45:45 +00:00
|
|
|
var client tapir.Service
|
2019-07-16 19:14:42 +00:00
|
|
|
client = new(tor.BaseOnionService)
|
2019-08-08 18:11:31 +00:00
|
|
|
client.Init(acn, sk, &id)
|
|
|
|
return client, id.Hostname()
|
2019-07-16 20:22:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Client will Connect and launch it's own Echo App goroutine.
|
2019-08-08 18:11:31 +00:00
|
|
|
func connectclient(client tapir.Service, key ed25519.PublicKey, group *sync.WaitGroup) {
|
2019-09-14 23:44:19 +00:00
|
|
|
client.Connect(utils.GetTorV3Hostname(key), new(SimpleApp))
|
2019-05-15 19:45:45 +00:00
|
|
|
|
|
|
|
// Once connected, it shouldn't take long to authenticate and run the application. So for the purposes of this demo
|
|
|
|
// we will wait a little while then exit.
|
|
|
|
time.Sleep(time.Second * 5)
|
2019-05-21 18:28:10 +00:00
|
|
|
|
2019-07-16 20:22:30 +00:00
|
|
|
conn, _ := client.GetConnection(utils.GetTorV3Hostname(key))
|
2019-07-16 19:14:42 +00:00
|
|
|
log.Debugf("Client has Auth: %v", conn.HasCapability(applications.AuthCapability))
|
2019-08-08 18:11:31 +00:00
|
|
|
AuthSuccess = true
|
|
|
|
group.Done()
|
2019-05-15 19:45:45 +00:00
|
|
|
}
|