move log and conectivity packages to standalone versions
the build was successful
Details
the build was successful
Details
This commit is contained in:
parent
5ec0bc8e1d
commit
03b9ff1fe8
|
@ -1,11 +1,11 @@
|
|||
package application
|
||||
|
||||
import (
|
||||
"git.openprivacy.ca/openprivacy/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
|
|
@ -2,12 +2,12 @@ package alicebot
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"git.openprivacy.ca/openprivacy/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"os"
|
||||
"time"
|
||||
|
|
|
@ -6,10 +6,10 @@ import (
|
|||
"git.openprivacy.ca/openprivacy/libricochet-go/application/examples/echobot/alicebot"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"time"
|
||||
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"os"
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ func main() {
|
|||
log.AddEverythingFromPattern("connectivity")
|
||||
|
||||
// Set up Tor
|
||||
acn, err := connectivity.StartTor(".", "")
|
||||
acn, err := tor.NewTorACN(".", "")
|
||||
if err != nil {
|
||||
log.Errorf("Unable to start Tor: %v", err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -5,10 +5,10 @@ import (
|
|||
"errors"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/auth/3edh"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/control"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
|
|
|
@ -5,10 +5,10 @@ import (
|
|||
"errors"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/auth/3edh"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/control"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
|
|
|
@ -4,9 +4,9 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/control"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"io"
|
||||
"sync"
|
||||
|
|
|
@ -3,9 +3,9 @@ package connection
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/control"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
)
|
||||
|
||||
// ControlChannel encapsulates logic for the control channel processing
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package connectivity
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// PrivateKey represents a private key using an unspecified algorithm.
|
||||
type PrivateKey interface{}
|
||||
|
||||
// ListenService is an address that was opened with Listen() and can Accept() new connections
|
||||
type ListenService interface {
|
||||
// AddressIdentity is the core "identity" part of an address, ex: rsjeuxzlexy4fvo75vrdtj37nrvlmvbw57n5mhypcjpzv3xkka3l4yyd
|
||||
AddressIdentity() string
|
||||
|
||||
// AddressFull is the full network address, ex: rsjeuxzlexy4fvo75vrdtj37nrvlmvbw57n5mhypcjpzv3xkka3l4yyd.onion:9878
|
||||
AddressFull() string
|
||||
|
||||
Accept() (net.Conn, error)
|
||||
Close()
|
||||
}
|
||||
|
||||
// ACN is Anonymous Communication Network implementation wrapper that supports Open for new connections and Listen to accept connections
|
||||
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()
|
||||
// Sets the calback function to be called when ACN status changes
|
||||
SetStatusCallback(callback func(int, string))
|
||||
|
||||
// Restarts the underlying connection
|
||||
Restart()
|
||||
|
||||
// Open takes a hostname and returns a net.conn to the derived endpoint
|
||||
// Open allows a client to resolve various hostnames to connections
|
||||
// The supported types are onions address are:
|
||||
// * ricochet:jlq67qzo6s4yp3sp
|
||||
// * jlq67qzo6s4yp3sp
|
||||
// * 127.0.0.1:55555|jlq67qzo6s4yp3sp - Localhost Connection
|
||||
Open(hostname string) (net.Conn, string, error)
|
||||
|
||||
// Listen takes a private key and a port and returns a ListenService for it
|
||||
Listen(identity PrivateKey, port int) (ListenService, error)
|
||||
|
||||
Close()
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package connectivity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type localListenService struct {
|
||||
l net.Listener
|
||||
}
|
||||
|
||||
type localProvider struct {
|
||||
}
|
||||
|
||||
func (ls *localListenService) AddressFull() string {
|
||||
return ls.l.Addr().String()
|
||||
}
|
||||
|
||||
func (ls *localListenService) AddressIdentity() string {
|
||||
return ls.l.Addr().String()
|
||||
}
|
||||
|
||||
func (ls *localListenService) Accept() (net.Conn, error) {
|
||||
return ls.l.Accept()
|
||||
}
|
||||
|
||||
func (ls *localListenService) 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"
|
||||
}
|
||||
|
||||
func (lp *localProvider) SetStatusCallback(callback func(int, string)) {
|
||||
// nop
|
||||
}
|
||||
|
||||
// WaitTillBootstrapped Blocks until underlying network is bootstrapped
|
||||
func (lp *localProvider) WaitTillBootstrapped() {
|
||||
}
|
||||
|
||||
func (lp *localProvider) Listen(identity PrivateKey, port int) (ListenService, error) {
|
||||
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%v", port))
|
||||
return &localListenService{l}, err
|
||||
}
|
||||
|
||||
func (lp *localProvider) Open(hostname string) (net.Conn, string, error) {
|
||||
// Localhost (127.0.0.1:55555|jlq67qzo6s4yp3sp) for testing
|
||||
addrParts := strings.Split(hostname, "|")
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp", addrParts[0])
|
||||
if err != nil {
|
||||
return nil, "", CannotResolveLocalTCPAddressError
|
||||
}
|
||||
conn, err := net.DialTCP("tcp", nil, tcpAddr)
|
||||
if err != nil {
|
||||
return nil, "", CannotDialLocalTCPAddressError
|
||||
}
|
||||
// return just the onion address, not the local override for the hostname
|
||||
return conn, addrParts[1], nil
|
||||
|
||||
}
|
||||
|
||||
func (lp *localProvider) Restart() {
|
||||
//noop
|
||||
}
|
||||
|
||||
func (lp *localProvider) Close() {
|
||||
|
||||
}
|
||||
|
||||
// LocalProvider returns a for testing use only local clearnet implementation of a ACN interface
|
||||
func LocalProvider() ACN {
|
||||
return &localProvider{}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
package connectivity
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var sysProcAttr = &syscall.SysProcAttr{}
|
|
@ -1,9 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package connectivity
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var sysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
|
@ -1,382 +0,0 @@
|
|||
package connectivity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"github.com/cretz/bine/control"
|
||||
"github.com/cretz/bine/process"
|
||||
"github.com/cretz/bine/tor"
|
||||
bineed255192 "github.com/cretz/bine/torutil/ed25519"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"net"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// CannotResolveLocalTCPAddressError is thrown when a local ricochet connection has the wrong format.
|
||||
CannotResolveLocalTCPAddressError = utils.Error("CannotResolveLocalTCPAddressError")
|
||||
// CannotDialLocalTCPAddressError is thrown when a connection to a local ricochet address fails.
|
||||
CannotDialLocalTCPAddressError = utils.Error("CannotDialLocalTCPAddressError")
|
||||
// CannotDialRicochetAddressError is thrown when a connection to a ricochet address fails.
|
||||
CannotDialRicochetAddressError = utils.Error("CannotDialRicochetAddressError")
|
||||
)
|
||||
|
||||
const (
|
||||
minStatusIntervalMs = 200
|
||||
maxStatusIntervalMs = 2000
|
||||
)
|
||||
|
||||
type onionListenService struct {
|
||||
os *tor.OnionService
|
||||
tp *torProvider
|
||||
}
|
||||
|
||||
type torProvider struct {
|
||||
t *tor.Tor
|
||||
dialer *tor.Dialer
|
||||
appDirectory string
|
||||
bundeledTorPath string
|
||||
lock sync.Mutex
|
||||
breakChan chan bool
|
||||
childListeners map[string]*onionListenService
|
||||
statusCallback func(int, string)
|
||||
}
|
||||
|
||||
func (ols *onionListenService) AddressFull() string {
|
||||
return ols.os.Addr().String()
|
||||
}
|
||||
|
||||
func (ols *onionListenService) AddressIdentity() string {
|
||||
return ols.os.Addr().String()[:56]
|
||||
}
|
||||
|
||||
func (ols *onionListenService) Accept() (net.Conn, error) {
|
||||
return ols.os.Accept()
|
||||
}
|
||||
|
||||
func (ols *onionListenService) Close() {
|
||||
ols.tp.unregisterListener(ols.AddressIdentity())
|
||||
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
|
||||
func (tp *torProvider) GetBootstrapStatus() (int, string) {
|
||||
if tp.t == nil {
|
||||
return -1, "error: no tor, trying to restart..."
|
||||
}
|
||||
kvs, err := tp.t.Control.GetInfo("status/bootstrap-phase")
|
||||
if err != nil {
|
||||
return -1, "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) {
|
||||
var onion = ""
|
||||
var privkey ed25519.PrivateKey
|
||||
|
||||
tp.lock.Lock()
|
||||
defer tp.lock.Unlock()
|
||||
|
||||
if tp.t == nil {
|
||||
return nil, errors.New("Tor Provider closed")
|
||||
}
|
||||
|
||||
switch pk := identity.(type) {
|
||||
case ed25519.PrivateKey:
|
||||
privkey = pk
|
||||
gpubk := pk.Public()
|
||||
switch pubk := gpubk.(type) {
|
||||
case ed25519.PublicKey:
|
||||
onion = utils.GetTorV3Hostname(pubk)
|
||||
}
|
||||
}
|
||||
|
||||
// Hack around tor detached onions not having a more obvious resume mechanism
|
||||
// So we use deterministic ports
|
||||
seedbytes := sha3.New224().Sum([]byte(onion))
|
||||
localport := int(seedbytes[0]) + (int(seedbytes[1]) << 8)
|
||||
if localport < 1024 { // this is not uniformly random, but we don't need it to be
|
||||
localport += 1024
|
||||
}
|
||||
|
||||
localListener, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(localport))
|
||||
|
||||
conf := &tor.ListenConf{NoWait: true, Version3: true, Key: identity, RemotePorts: []int{port}, Detach: true, DiscardKey: true, LocalListener: localListener}
|
||||
os, err := tp.t.Listen(nil, conf)
|
||||
if err != nil && strings.Contains(err.Error(), "550 Unspecified Tor error: Onion address collision") {
|
||||
os = &tor.OnionService{Tor: tp.t, LocalListener: localListener, ID: onion, Version3: true, Key: bineed255192.FromCryptoPrivateKey(privkey), ClientAuths: make(map[string]string, 0), RemotePorts: []int{port}}
|
||||
err = nil
|
||||
}
|
||||
// Not set in t.Listen if supplied, we want it to handle this however
|
||||
os.CloseLocalListenerOnClose = true
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ols := &onionListenService{os: os, tp: tp}
|
||||
tp.childListeners[ols.AddressIdentity()] = ols
|
||||
return ols, nil
|
||||
}
|
||||
|
||||
func (tp *torProvider) Restart() {
|
||||
if tp.statusCallback != nil {
|
||||
tp.statusCallback(0, "rebooting")
|
||||
}
|
||||
tp.restart()
|
||||
}
|
||||
|
||||
func (tp *torProvider) Open(hostname string) (net.Conn, string, error) {
|
||||
tp.lock.Lock()
|
||||
|
||||
if tp.t == nil {
|
||||
tp.lock.Unlock()
|
||||
return nil, hostname, errors.New("Tor is offline")
|
||||
}
|
||||
tp.lock.Unlock()
|
||||
|
||||
resolvedHostname := hostname
|
||||
if strings.HasPrefix(hostname, "ricochet:") {
|
||||
addrParts := strings.Split(hostname, ":")
|
||||
resolvedHostname = addrParts[1]
|
||||
}
|
||||
|
||||
conn, err := tp.dialer.Dial("tcp", resolvedHostname+".onion:9878")
|
||||
return conn, resolvedHostname, err
|
||||
}
|
||||
|
||||
func (tp *torProvider) Close() {
|
||||
for _, child := range tp.childListeners {
|
||||
child.Close()
|
||||
}
|
||||
|
||||
tp.lock.Lock()
|
||||
defer tp.lock.Unlock()
|
||||
tp.breakChan <- true
|
||||
if tp.t != nil {
|
||||
tp.t.Close()
|
||||
tp.t = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *torProvider) SetStatusCallback(callback func(int, string)) {
|
||||
tp.lock.Lock()
|
||||
defer tp.lock.Unlock()
|
||||
tp.statusCallback = callback
|
||||
}
|
||||
|
||||
// StartTor creates/starts a Tor ACN and returns a usable ACN object
|
||||
func StartTor(appDirectory string, bundledTorPath string) (ACN, error) {
|
||||
tp, err := startTor(appDirectory, bundledTorPath)
|
||||
if err == nil {
|
||||
tp.dialer, err = tp.t.Dialer(nil, &tor.DialConf{})
|
||||
if err == nil {
|
||||
go tp.monitorRestart()
|
||||
}
|
||||
}
|
||||
return tp, err
|
||||
}
|
||||
|
||||
// newHideCmd creates a Creator function for bine which generates a cmd that one windows will hide the dosbox
|
||||
func newHideCmd(exePath string) process.Creator {
|
||||
return process.CmdCreatorFunc(func(ctx context.Context, args ...string) (*exec.Cmd, error) {
|
||||
cmd := exec.CommandContext(ctx, exePath, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.SysProcAttr = sysProcAttr
|
||||
return cmd, nil
|
||||
})
|
||||
}
|
||||
|
||||
func startTor(appDirectory string, bundledTorPath string) (*torProvider, error) {
|
||||
dataDir := path.Join(appDirectory, "tor")
|
||||
os.MkdirAll(dataDir, 0700)
|
||||
tp := &torProvider{appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool), statusCallback: nil}
|
||||
|
||||
// attempt connect to system tor
|
||||
log.Debugf("dialing system tor control port\n")
|
||||
controlport, err := dialControlPort(9051)
|
||||
|
||||
if err == nil {
|
||||
// TODO: configurable auth
|
||||
err := controlport.Authenticate("")
|
||||
if err == nil {
|
||||
log.Debugln("connected to control port")
|
||||
pinfo, err := controlport.ProtocolInfo()
|
||||
if err == nil && minTorVersionReqs(pinfo.TorVersion) {
|
||||
log.Debugln("OK version " + pinfo.TorVersion)
|
||||
tp.t = createFromExisting(controlport, dataDir)
|
||||
return tp, nil
|
||||
}
|
||||
controlport.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// if not, try running system tor
|
||||
if checkCmdlineTorVersion("tor") {
|
||||
t, err := tor.Start(nil, &tor.StartConf{EnableNetwork: true, DataDir: dataDir, DebugWriter: nil, ProcessCreator: newHideCmd("tor")})
|
||||
if err == nil {
|
||||
tp.t = t
|
||||
return tp, nil
|
||||
}
|
||||
log.Debugf("Error connecting to self-run system tor: %v\n", err)
|
||||
}
|
||||
|
||||
// try running bundledTor
|
||||
if bundledTorPath != "" && checkCmdlineTorVersion(bundledTorPath) {
|
||||
log.Debugln("using bundled tor '" + bundledTorPath + "'")
|
||||
t, err := tor.Start(nil, &tor.StartConf{EnableNetwork: true, DataDir: dataDir, ExePath: bundledTorPath, DebugWriter: nil, ProcessCreator: newHideCmd(bundledTorPath)})
|
||||
if err != nil {
|
||||
log.Debugf("Error running bundled tor: %v\n", err)
|
||||
}
|
||||
tp.t = t
|
||||
return tp, err
|
||||
}
|
||||
return nil, errors.New("Could not connect to or start Tor that met requirments (min Tor version 0.3.5.x)")
|
||||
}
|
||||
|
||||
func (tp *torProvider) unregisterListener(id string) {
|
||||
tp.lock.Lock()
|
||||
defer tp.lock.Unlock()
|
||||
delete(tp.childListeners, id)
|
||||
}
|
||||
|
||||
func (tp *torProvider) monitorRestart() {
|
||||
lastBootstrapProgress := 0
|
||||
interval := minStatusIntervalMs
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Millisecond * time.Duration(interval)):
|
||||
prog, status := tp.GetBootstrapStatus()
|
||||
|
||||
if prog == -1 && tp.t != nil {
|
||||
if tp.statusCallback != nil {
|
||||
tp.statusCallback(prog, status)
|
||||
}
|
||||
tp.restart()
|
||||
interval = minStatusIntervalMs
|
||||
} else if prog != lastBootstrapProgress {
|
||||
if tp.statusCallback != nil {
|
||||
tp.statusCallback(prog, status)
|
||||
}
|
||||
interval = minStatusIntervalMs
|
||||
} else {
|
||||
if interval < maxStatusIntervalMs {
|
||||
interval *= 2
|
||||
}
|
||||
}
|
||||
lastBootstrapProgress = prog
|
||||
case <-tp.breakChan:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *torProvider) restart() {
|
||||
|
||||
for _, child := range tp.childListeners {
|
||||
child.Close()
|
||||
}
|
||||
|
||||
tp.lock.Lock()
|
||||
defer tp.lock.Unlock()
|
||||
|
||||
tp.t.Close()
|
||||
tp.t = nil
|
||||
|
||||
for {
|
||||
newTp, err := startTor(tp.appDirectory, tp.bundeledTorPath)
|
||||
if err == nil {
|
||||
tp.t = newTp.t
|
||||
tp.dialer, _ = tp.t.Dialer(nil, &tor.DialConf{})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createFromExisting(controlport *control.Conn, datadir string) *tor.Tor {
|
||||
t := &tor.Tor{
|
||||
Process: nil,
|
||||
Control: controlport,
|
||||
ProcessCancelFunc: nil,
|
||||
DataDir: datadir,
|
||||
DeleteDataDirOnClose: false,
|
||||
DebugWriter: nil,
|
||||
StopProcessOnClose: false,
|
||||
GeoIPCreatedFile: "",
|
||||
GeoIPv6CreatedFile: "",
|
||||
}
|
||||
t.Control.DebugWriter = t.DebugWriter
|
||||
|
||||
t.EnableNetwork(nil, true)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func checkCmdlineTorVersion(torCmd string) bool {
|
||||
cmd := exec.Command(torCmd, "--version")
|
||||
cmd.SysProcAttr = sysProcAttr
|
||||
out, err := cmd.CombinedOutput()
|
||||
re := regexp.MustCompile("[0-1]\\.[0-9]\\.[0-9]\\.[0-9]")
|
||||
sysTorVersion := re.Find(out)
|
||||
log.Infoln("tor version: " + string(sysTorVersion))
|
||||
return err == nil && minTorVersionReqs(string(sysTorVersion))
|
||||
}
|
||||
|
||||
// returns true if supplied version meets our min requirments
|
||||
// min requirement: 0.3.5.x
|
||||
func minTorVersionReqs(torversion string) bool {
|
||||
torversions := strings.Split(torversion, ".") //eg: 0.3.4.8 or 0.3.5.1-alpha
|
||||
log.Debugf("torversions: %v", torversions)
|
||||
tva, _ := strconv.Atoi(torversions[0])
|
||||
tvb, _ := strconv.Atoi(torversions[1])
|
||||
tvc, _ := strconv.Atoi(torversions[2])
|
||||
return tva > 0 || (tva == 0 && (tvb > 3 || (tvb == 3 && tvc >= 5)))
|
||||
}
|
||||
|
||||
func dialControlPort(port int) (*control.Conn, error) {
|
||||
textConn, err := textproto.Dial("tcp", "127.0.0.1:"+strconv.Itoa(port))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return control.NewConn(textConn), nil
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package connectivity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func getStatusCallback(progChan chan int) func(int, string) {
|
||||
return func(prog int, status string) {
|
||||
fmt.Printf("%v %v\n", prog, status)
|
||||
progChan <- prog
|
||||
}
|
||||
}
|
||||
|
||||
func TestTorProvider(t *testing.T) {
|
||||
progChan := make(chan int)
|
||||
acn, err := StartTor(".", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
acn.SetStatusCallback(getStatusCallback(progChan))
|
||||
|
||||
progress := 0
|
||||
for progress < 100 {
|
||||
progress = <-progChan
|
||||
}
|
||||
|
||||
acn.Close()
|
||||
}
|
7
go.mod
7
go.mod
|
@ -1,12 +1,11 @@
|
|||
module git.openprivacy.ca/openprivacy/libricochet-go
|
||||
|
||||
require (
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.1.0
|
||||
git.openprivacy.ca/openprivacy/log v1.0.0
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412
|
||||
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca
|
||||
github.com/golang/protobuf v1.2.0
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20190128193316-c7b33c32a30b
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
|
||||
)
|
||||
|
||||
|
|
19
go.sum
19
go.sum
|
@ -1,7 +1,9 @@
|
|||
git.openprivacy.ca/openprivacy/connectivity v1.1.0 h1:9PEeKuPdoIRYeA62BUkBW2BfK4KqKEXz1fvUxZoP4xs=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
||||
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
|
||||
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
|
||||
github.com/cretz/bine v0.1.0 h1:1/fvhLE+fk0bPzjdO5Ci+0ComYxEMuB1JhM4X5skT3g=
|
||||
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
||||
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw=
|
||||
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
|
@ -13,9 +15,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
golang.org/x/crypto v0.0.0-20190128193316-c7b33c32a30b h1:Ib/yptP38nXZFMwqWSip+OKuMP9OkyDe3p+DssP8n9w=
|
||||
golang.org/x/crypto v0.0.0-20190128193316-c7b33c32a30b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w=
|
||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
219
log/log.go
219
log/log.go
|
@ -1,219 +0,0 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
golog "log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Level indicates the level a log should be classified at
|
||||
type Level int
|
||||
|
||||
// The possible levels a log can have
|
||||
const (
|
||||
LevelDebug Level = iota + 1
|
||||
LevelInfo
|
||||
LevelWarn
|
||||
LevelError
|
||||
)
|
||||
|
||||
var levelString = map[Level]string{LevelDebug: "[DBUG]", LevelInfo: "[INFO]", LevelWarn: "[WARN]", LevelError: "[ERR ]"}
|
||||
|
||||
// Logger is a go Logger wrapper that adds log levels and pattern filtering
|
||||
// It allows high level 'log level' filtering broadly
|
||||
// It allows allows two addition levels of filtering:
|
||||
// everythingFrom which allows inclusion of packages/patterns along with general logging
|
||||
// nothingExcept which allows focusing on just listed areas
|
||||
type Logger struct {
|
||||
logger *golog.Logger
|
||||
level Level
|
||||
nothingExceptPatterns []string
|
||||
everythingFromPatterns []string
|
||||
excludeFromPatterns []string
|
||||
}
|
||||
|
||||
// New returns a new Logger with a filter set to the supplied level
|
||||
func New(level Level) *Logger {
|
||||
return &Logger{logger: golog.New(os.Stderr, "", golog.Ldate|golog.Ltime), level: level, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0)}
|
||||
}
|
||||
|
||||
// NewFile returns a new Logger that logs to the supplied file with a filter set to the supplied level
|
||||
func NewFile(level Level, filename string) (*Logger, error) {
|
||||
logfile, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Logger{logger: golog.New(logfile, "", golog.Ldate|golog.Ltime), level: level, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0)}, nil
|
||||
}
|
||||
|
||||
var std = New(LevelWarn)
|
||||
|
||||
// SetStd sets the default logger all other functions use
|
||||
func SetStd(logger *Logger) {
|
||||
std = logger
|
||||
}
|
||||
|
||||
// filter
|
||||
func (l *Logger) filter(level Level) bool {
|
||||
|
||||
_, file, _, ok := runtime.Caller(3)
|
||||
if !ok {
|
||||
file = "???"
|
||||
}
|
||||
|
||||
for _, pattern := range l.excludeFromPatterns {
|
||||
if strings.Contains(file, pattern) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for _, pattern := range l.everythingFromPatterns {
|
||||
if strings.Contains(file, pattern) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
for _, pattern := range l.nothingExceptPatterns {
|
||||
if strings.Contains(file, pattern) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if len(l.nothingExceptPatterns) > 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return l.aboveLevel(level)
|
||||
}
|
||||
|
||||
func (l *Logger) aboveLevel(level Level) bool {
|
||||
return level >= l.level
|
||||
}
|
||||
|
||||
// SetLevel adjusts the output filter by logging level
|
||||
func (l *Logger) SetLevel(level Level) {
|
||||
l.level = level
|
||||
}
|
||||
|
||||
// AddNothingExceptFilter enables strong filtering showing logs only for things on the approved list, adding this pattern to the list
|
||||
func (l *Logger) AddNothingExceptFilter(pattern string) {
|
||||
l.nothingExceptPatterns = append(l.nothingExceptPatterns, pattern)
|
||||
}
|
||||
|
||||
// AddEverythingFromPattern adds a pattern to skip log level filtering, guaranteeing all logs matching the pattern are seen
|
||||
func (l *Logger) AddEverythingFromPattern(pattern string) {
|
||||
l.everythingFromPatterns = append(l.everythingFromPatterns, pattern)
|
||||
}
|
||||
|
||||
// ExcludeFromPattern adds a pattern to exclude logs from
|
||||
func (l *Logger) ExcludeFromPattern(pattern string) {
|
||||
l.excludeFromPatterns = append(l.excludeFromPatterns, pattern)
|
||||
}
|
||||
|
||||
func (l *Logger) header(level Level) string {
|
||||
_, file, _, ok := runtime.Caller(3)
|
||||
if !ok {
|
||||
file = "???"
|
||||
} else {
|
||||
short := file
|
||||
count := 0
|
||||
for i := len(file) - 1; i > 0; i-- {
|
||||
if file[i] == '/' {
|
||||
short = file[i+1:]
|
||||
count++
|
||||
if count == 2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
file = short
|
||||
}
|
||||
return file + " " + levelString[level] + " "
|
||||
}
|
||||
|
||||
// Printf outputs the format and variables, assuming it passes the filter levels
|
||||
func (l *Logger) Printf(level Level, format string, v ...interface{}) {
|
||||
if l.filter(level) {
|
||||
l.logger.Output(3, l.header(level)+fmt.Sprintf(format, v...))
|
||||
}
|
||||
}
|
||||
|
||||
// Println outputs the variables assuming the filter levels are passed
|
||||
func (l *Logger) Println(level Level, v ...interface{}) {
|
||||
if l.filter(level) {
|
||||
l.logger.Output(3, l.header(level)+fmt.Sprintln(v...))
|
||||
}
|
||||
}
|
||||
|
||||
// SetLevel changes the filtering level of the system logger
|
||||
func SetLevel(level Level) {
|
||||
std.SetLevel(level)
|
||||
}
|
||||
|
||||
// AddNothingExceptFilter enables strong filtering showing logs only for things on the approved list, adding this pattern to the list
|
||||
func AddNothingExceptFilter(pattern string) {
|
||||
std.AddNothingExceptFilter(pattern)
|
||||
}
|
||||
|
||||
// AddEverythingFromPattern adds a pattern to skip log level filtering, guaranteeing all logs matching the pattern are seen
|
||||
func AddEverythingFromPattern(pattern string) {
|
||||
std.AddEverythingFromPattern(pattern)
|
||||
}
|
||||
|
||||
// ExcludeFromPattern adds a pattern to exclude logs from
|
||||
func ExcludeFromPattern(pattern string) {
|
||||
std.ExcludeFromPattern(pattern)
|
||||
}
|
||||
|
||||
// Printf outputs the format with variables assuming it passes the filter level
|
||||
func Printf(level Level, format string, v ...interface{}) {
|
||||
std.Printf(level, format, v...)
|
||||
}
|
||||
|
||||
// Println outputs the varibles assuming they pass the filter level
|
||||
func Println(level Level, v ...interface{}) {
|
||||
std.Println(level, v...)
|
||||
}
|
||||
|
||||
// Debugf outputs the format and variables at the Debug level
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
std.Printf(LevelDebug, format, v...)
|
||||
}
|
||||
|
||||
// Infof outputs the format and variables at the Info level
|
||||
func Infof(format string, v ...interface{}) {
|
||||
std.Printf(LevelInfo, format, v...)
|
||||
}
|
||||
|
||||
// Warnf outputs the format and variables at the Warning level
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
std.Printf(LevelWarn, format, v...)
|
||||
}
|
||||
|
||||
// Errorf outputs the format and variables at the Error level
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
std.Printf(LevelError, format, v...)
|
||||
}
|
||||
|
||||
// Debugln outputs the variables at the Debug level
|
||||
func Debugln(v ...interface{}) {
|
||||
std.Println(LevelDebug, v...)
|
||||
}
|
||||
|
||||
// Infoln outputs the variables at the Info level
|
||||
func Infoln(v ...interface{}) {
|
||||
std.Println(LevelInfo, v...)
|
||||
}
|
||||
|
||||
// Warnln outputs the variables at the Warn level
|
||||
func Warnln(v ...interface{}) {
|
||||
std.Println(LevelWarn, v...)
|
||||
}
|
||||
|
||||
// Errorln outputs the variables at the Error level
|
||||
func Errorln(v ...interface{}) {
|
||||
std.Println(LevelError, v...)
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package goricochet
|
||||
|
||||
import (
|
||||
"git.openprivacy.ca/openprivacy/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"io"
|
||||
"net"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package goricochet
|
||||
|
||||
import (
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/connectivity"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -19,7 +19,7 @@ func SimpleServer() {
|
|||
}
|
||||
|
||||
func TestRicochetOpen(t *testing.T) {
|
||||
acn := connectivity.LocalProvider()
|
||||
acn := connectivity.NewLocalACN()
|
||||
go SimpleServer()
|
||||
// Wait for Server to Initialize
|
||||
time.Sleep(time.Second)
|
||||
|
@ -46,7 +46,7 @@ func BadServer() {
|
|||
}
|
||||
|
||||
func TestRicochetOpenWithError(t *testing.T) {
|
||||
acn := connectivity.LocalProvider()
|
||||
acn := connectivity.NewLocalACN()
|
||||
go BadServer()
|
||||
// Wait for Server to Initialize
|
||||
time.Sleep(time.Second)
|
||||
|
@ -57,7 +57,7 @@ func TestRicochetOpenWithError(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRicochetOpenWithNoServer(t *testing.T) {
|
||||
acn := connectivity.LocalProvider()
|
||||
acn := connectivity.NewLocalACN()
|
||||
_, err := Open(acn, "127.0.0.1:11002|abcdefghijklmno.onion")
|
||||
if err == nil {
|
||||
t.Errorf("Open should have failed because of bad version negotiation.")
|
||||
|
|
|
@ -2,12 +2,12 @@ package testing
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
@ -96,7 +96,7 @@ func TestApplicationIntegration(t *testing.T) {
|
|||
log.SetLevel(log.LevelDebug)
|
||||
startGoRoutines := runtime.NumGoroutine()
|
||||
|
||||
acn, err := connectivity.StartTor(".", "")
|
||||
acn, err := tor.NewTorACN(".", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not start tor: %v", err)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/openprivacy/log"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
"io"
|
||||
"sync"
|
||||
|
|
Reference in New Issue