Browse Source

ACN Process Management (#345)

ACN Process Management
update connectivity
use filepath instead of path for join

Co-authored-by: Dan Ballard <dan@mindstab.net>
Reviewed-on: https://git.openprivacy.ca/cwtch.im/ui/pulls/345
pull/346/head
Sarah Jamie Lewis 3 months ago
committed by Dan Ballard
parent
commit
e2ab860c72
7 changed files with 146 additions and 20 deletions
  1. +1
    -1
      README.md
  2. +3
    -4
      go.mod
  3. +17
    -0
      go.sum
  4. +42
    -0
      go/os/kill_unix.go
  5. +48
    -0
      go/os/kill_windows.go
  6. +2
    -0
      go/ui/settings.go
  7. +33
    -15
      main.go

+ 1
- 1
README.md View File

@@ -1,5 +1,5 @@
# Cwtch - UI
This codebase provides a graphical user interface for Desktop and Android for [Cwtch: Privacy Preserving Infrastructure for Asynchronous, Decentralized and Metadata Resistant Applications](https://git.openprivacy.ca/cwtch.im/cwtch)

# Security


+ 3
- 4
go.mod View File

@@ -3,12 +3,11 @@ module cwtch.im/ui
go 1.12

require (
cwtch.im/cwtch v0.4.1
git.openprivacy.ca/openprivacy/connectivity v1.2.2
cwtch.im/cwtch v0.4.2
git.openprivacy.ca/openprivacy/connectivity v1.3.1
git.openprivacy.ca/openprivacy/log v1.0.1
github.com/gopherjs/gopherjs v0.0.0-20200209183636-89e6cbcd0b6d // indirect
github.com/therecipe/qt v0.0.0-20200126204426-5074eb6d8c41
github.com/therecipe/qt/internal/binding/files/docs/5.12.0 v0.0.0-20200126204426-5074eb6d8c41 // indirect
github.com/therecipe/qt/internal/binding/files/docs/5.13.0 v0.0.0-20200126204426-5074eb6d8c41 // indirect
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 // indirect
)
)

+ 17
- 0
go.sum View File

@@ -12,6 +12,8 @@ cwtch.im/cwtch v0.4.0 h1:lhGQiYRBqSF0Pif9QttYVL4B1Oy1vc0v3cZejL7c7x4=
cwtch.im/cwtch v0.4.0/go.mod h1:EvZQDbvXNu38m785dWF0MMljqJzwWrNTFT40HvoEAhI=
cwtch.im/cwtch v0.4.1 h1:wjf/3Vw5fDByEwwnXqWrPtpKsXTLk0oz0PqNGYcR+MQ=
cwtch.im/cwtch v0.4.1/go.mod h1:EvZQDbvXNu38m785dWF0MMljqJzwWrNTFT40HvoEAhI=
cwtch.im/cwtch v0.4.2 h1:qIjTOwKkBf1tIsat27gXPriXSZXtKcTJ8Sf7E/2+GXc=
cwtch.im/cwtch v0.4.2/go.mod h1:10gBkMSqAH95Pz4jTx5mpIHE+dkn+4kRC4BFTxWuQK8=
cwtch.im/tapir v0.1.15 h1:XSCWOvjmNkzMT2IceFgTBXWGKtYfr3a8o+La1s10OhE=
cwtch.im/tapir v0.1.15/go.mod h1:HzezugpEx+nZ3LdyDsl0w6n45IJYnOt8uqldkLWmaqs=
cwtch.im/tapir v0.1.17 h1:2jVZUe1a88tMI4aJPvRTO4Id3NN3PsM62cT5lntEChk=
@@ -20,6 +22,8 @@ cwtch.im/tapir v0.1.18 h1:Fs/jL9ZRyel/A1D/BYzIPEVQau8y5BJg44yA+GQDbSM=
cwtch.im/tapir v0.1.18/go.mod h1:/IrAI6CBHfgzsfgRT8WHVb1P9fCCz7+45hfsdkKn8Zg=
cwtch.im/tapir v0.2.0 h1:7MkoR5+uEuPW34/O0GZRidnIjq/01Cfm8nl5IRuqpGc=
cwtch.im/tapir v0.2.0/go.mod h1:xzzZ28adyUXNkYL1YodcHsAiTt3IJ8Loc29YVn9mIEQ=
git.openprivacy.ca/openprivacy/bine v0.0.3 h1:PSHUmNqaW7BZUX8n2eTDeNbjsuRe+t5Ae0Og+P+jDM0=
git.openprivacy.ca/openprivacy/bine v0.0.3/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLyqtXc46XBcnuXm/mU=
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
git.openprivacy.ca/openprivacy/connectivity v1.1.1 h1:hKxBOmxP7Jdu3K1BJ93mRtKNiWUoP6YHt/o2snE2Z0w=
git.openprivacy.ca/openprivacy/connectivity v1.1.1/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
@@ -35,6 +39,8 @@ git.openprivacy.ca/openprivacy/connectivity v1.2.1 h1:oRL56TR9ZQnKkGkTIQ9wYbJ2Ik
git.openprivacy.ca/openprivacy/connectivity v1.2.1/go.mod h1:B7vzuVmChJtSKoh0ezph5vu6DQ0gIk0zHUNG6IgXCcA=
git.openprivacy.ca/openprivacy/connectivity v1.2.2 h1:CeuZB469xHMHxygxZD559CkRUAGR7ct4oeSlsAHQmKo=
git.openprivacy.ca/openprivacy/connectivity v1.2.2/go.mod h1:B7vzuVmChJtSKoh0ezph5vu6DQ0gIk0zHUNG6IgXCcA=
git.openprivacy.ca/openprivacy/connectivity v1.3.0 h1:e2EeV6CaMNwOb+PzAjF0hGCeOqAPagRaDL4en5ITf7U=
git.openprivacy.ca/openprivacy/connectivity v1.3.0/go.mod h1:s0/QhONuUqJQfYTAgUlu+ya7G3Ov6bKgpT5QkOhVxDI=
git.openprivacy.ca/openprivacy/libricochet-go v1.0.11 h1:C7QFFzG0p5XKu0zcOIdLGwEpA9uU0BceBM7CfVK5D40=
git.openprivacy.ca/openprivacy/libricochet-go v1.0.11/go.mod h1:yTMps/ZpYS+BNBBvANsNAft28FXrBvFHQauMYNWPrwE=
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13 h1:Z86uL9K47onznY1wP1P/wWfWMbbyvk6xnCp94R180os=
@@ -104,6 +110,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI=
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f h1:06ICDSmDOBUC9jwgv44ngvyHzwudJNLa5H+rbCyDFRY=
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
@@ -135,6 +142,9 @@ golang.org/x/crypto v0.0.0-20200320181102-891825fb96df h1:lDWgvUvNnaTnNBc/dwOty8
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 h1:IhZPbxNd1UjBCaD5AfpSSbJTRlp+ZSuyuH5uoksNS04=
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -149,6 +159,8 @@ golang.org/x/net v0.0.0-20200320181208-1c781a10960a h1:KaxWXSFrOaE2ptiOotI+zFdzH
golang.org/x/net v0.0.0-20200320181208-1c781a10960a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -170,7 +182,11 @@ golang.org/x/sys v0.0.0-20200320181252-af34d8274f85/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789 h1:FF0rjo15h51+N6642mf5S3QuplmKo2aCrJUYkHTx85s=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -188,3 +204,4 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 42
- 0
go/os/kill_unix.go View File

@@ -0,0 +1,42 @@
// +build unix linux android

package os

import (
"git.openprivacy.ca/openprivacy/log"
"os/exec"
"strconv"
"strings"
)

// CheckProcessAndKill first executes a process search on the system by the last known pid, if the name of the
// process matches the expected name, then it is killed.
// On unix systems the command "ps" is practically universal and should suffice for this...
func CheckProcessAndKill(pid uint64, processName string) {
log.Debugf("killing: %v", pid)
bytes,err := exec.Command("ps", "-p", strconv.Itoa(int(pid)), "-o", "command").Output()
if err == nil {
// check for a binary @ "/<process_name>"
if strings.HasSuffix(string(bytes),"/"+processName) {
Kill(pid)
return
}
log.Debugf("pid did not relate to expected process, not killing out of caution")
return
}
// no such process
log.Debugf("no such process %v", pid)
}

// Kill a process based on pid
func Kill(pid uint64) {
log.Debugf("killing: %v", pid)
bytes,err := exec.Command("kill", strconv.Itoa(int(pid))).Output()
if err == nil {
log.Debugf("kill %v successful: %s", pid, bytes)
} else {
// this might now always succeed
log.Debugf("could not kill pid: %v %v", pid, err)
}
return
}

+ 48
- 0
go/os/kill_windows.go View File

@@ -0,0 +1,48 @@
// +build windows
package os

import (
"git.openprivacy.ca/openprivacy/log"
"os/exec"
"strconv"
"strings"
)

// CheckProcessAndKill first executes a process search on the system by the last known pid, if the name of the
// process matches the expected name, then it is killed.
// On windows this uses tasklist...
func CheckProcessAndKill(pid uint64, processName string) {
log.Debugf("looking up process: %v", pid)
bytes,err := exec.Command("tasklist", "/fi", "pid eq "+strconv.Itoa(int(pid))).Output()
if err == nil {
// Output will be something like this:
//
// Image Name PID Session Name Session# Mem Usage
// ========================= ======== ================ =========== ============
// process.exe <PID> Services 0 8,936 K
lines := strings.Split(strings.TrimSpace(string(bytes)),"\n")
log.Debugf("%v\n", lines)

// check for "<process>.exe"
if len(lines) >= 3 && strings.HasPrefix(strings.ToLower(strings.TrimSpace(lines[2])),processName+".exe") {
Kill(pid)
return
}
log.Debugf("pid did not relate to expected process, not attempting process kill out of caution")
return
}
log.Debugf("error checking process: %v", err)
}

// Kill a process based on pid
func Kill(pid uint64) {
log.Debugf("killing: %v", pid)
bytes,err := exec.Command("taskkill", "/F", "/PID", strconv.Itoa(int(pid))).Output()
if err == nil {
log.Debugf("kill %v successful: %s", pid, bytes)
} else {
// this might now always succeed
log.Debugf("could not kill pid: %v %v", pid, err)
}
return
}

+ 2
- 0
go/ui/settings.go View File

@@ -19,12 +19,14 @@ type GlobalSettings struct {
Zoom float32
Locale string
Theme string
PreviousPid int64
}

var DefaultGlobalSettings = GlobalSettings{
Zoom: 1.0,
Locale: "en",
Theme: "light",
PreviousPid: -1,
}

func InitGlobalSettingsFile(directory string, password string) error {


+ 33
- 15
main.go View File

@@ -5,6 +5,7 @@ import (
libapp "cwtch.im/cwtch/app"
"cwtch.im/cwtch/event/bridge"
"cwtch.im/ui/go/handlers"
os2 "cwtch.im/ui/go/os"
"cwtch.im/ui/go/the"
"cwtch.im/ui/go/ui"
"cwtch.im/ui/go/ui/android"
@@ -21,7 +22,6 @@ import (
mrand "math/rand"
"os"
"os/user"
"path"
"path/filepath"
"runtime"
"time"
@@ -74,19 +74,19 @@ func main() {
if os.Getenv("CWTCH_FOLDER") != "" {
the.CwtchDir = os.Getenv("CWTCH_FOLDER")
} else if runtime.GOOS == "android" {
the.CwtchDir = path.Join(androidBaseDir, "files")
the.CwtchDir = filepath.Join(androidBaseDir, "files")
} else {
usr, err := user.Current()
if err != nil {
log.Errorf("\nerror: could not load current user: %v\n", err)
os.Exit(1)
}
the.CwtchDir = path.Join(usr.HomeDir, ".cwtch")
the.CwtchDir = filepath.Join(usr.HomeDir, ".cwtch")
}

if buildVer == "" && os.Getenv("CWTCH_FOLDER") == "" {
log.Infoln("Development build: using dev directory for dev profiles")
the.CwtchDir = path.Join(the.CwtchDir, "dev")
the.CwtchDir = filepath.Join(the.CwtchDir, "dev")
}

the.ACN = nil
@@ -135,7 +135,7 @@ func mainUi(flagLocal bool, flagClientUI bool) {

app := gui.NewQGuiApplication(len(os.Args), os.Args)
// our globals
err := ui.InitGlobalSettingsFile(path.Join(the.CwtchDir, "global"), the.AppPassword)
err := ui.InitGlobalSettingsFile(filepath.Join(the.CwtchDir, "global"), the.AppPassword)
if err != nil {
log.Errorf("Could not access global ui config: %v\n", err)
os.Exit(-1)
@@ -152,7 +152,7 @@ func mainUi(flagLocal bool, flagClientUI bool) {
if runtime.GOOS == "windows" {
dir = "/" + dir
}
gcd.SetAssetPath("file://" + path.Join(dir, "assets") + "/")
gcd.SetAssetPath("file://" + filepath.Join(dir, "assets") + "/")
}

if buildVer != "" {
@@ -215,24 +215,24 @@ func mainUi(flagLocal bool, flagClientUI bool) {
func loadACN() {
torpath := "tor"
if runtime.GOOS == "android" {
torpath = path.Join(androidBaseDir, "lib/libtor.so")
torpath = filepath.Join(androidBaseDir, "lib/libtor.so")
} else if runtime.GOOS == "windows" {
ex, err := os.Executable()
if err != nil {
ex = ""
}
exPath := filepath.Dir(ex)
torpath = path.Join(exPath, "tor-0.3.5.7", "Tor", "tor.exe")
torpath = filepath.Join(exPath, "tor-0.3.5.7", "Tor", "tor.exe")
} else {
dir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
if _, err := os.Stat(path.Join(dir, "tor")); os.IsNotExist(err) {
if _, err := os.Stat(path.Join(dir, "deploy", "linux", "tor")); os.IsNotExist(err) {
if _, err := os.Stat(filepath.Join(dir, "tor")); os.IsNotExist(err) {
if _, err := os.Stat(filepath.Join(dir, "deploy", "linux", "tor")); os.IsNotExist(err) {
log.Warnln("Cannot find bundled Tor")
} else {
torpath = path.Join(dir, "deploy", "linux", "tor")
torpath = filepath.Join(dir, "deploy", "linux", "tor")
}
} else {
torpath = path.Join(dir, "tor")
torpath = filepath.Join(dir, "tor")
}
}

@@ -250,7 +250,7 @@ func loadACN() {

// generate torrc on the fly
// TODO if we have been configured for it, use system tor (like orbot) - we need a way to config this in the UI first
tor.NewTorrc().WithSocksPort(port).WithOnionTrafficOnly().WithControlPort(controlPort).WithHashedPassword(base64.StdEncoding.EncodeToString(key)).Build(path.Join(the.CwtchDir, "tor", "torrc"))
tor.NewTorrc().WithSocksPort(port).WithOnionTrafficOnly().WithControlPort(controlPort).WithHashedPassword(base64.StdEncoding.EncodeToString(key)).Build(filepath.Join(the.CwtchDir, "tor", "torrc"))
the.ACN, err = tor.NewTorACNWithAuth(the.CwtchDir, torpath, controlPort, tor.HashedPasswordAuthenticator{base64.StdEncoding.EncodeToString(key)})

if err != nil {
@@ -262,8 +262,8 @@ func loadACN() {

func loadNetworkingAndFiles(gcd *ui.GrandCentralDispatcher, service bool, clientUI bool) {
if service || clientUI || runtime.GOOS == "android" {
clientIn := path.Join(the.CwtchDir, "clientIn")
serviceIn := path.Join(the.CwtchDir, "serviceIn")
clientIn := filepath.Join(the.CwtchDir, "clientIn")
serviceIn := filepath.Join(the.CwtchDir, "serviceIn")
if service {
loadACN()
serviceBridge := bridge.NewPipeBridgeService(serviceIn, clientIn)
@@ -275,9 +275,27 @@ func loadNetworkingAndFiles(gcd *ui.GrandCentralDispatcher, service bool, client
the.CwtchApp = libapp.NewAppClient(the.CwtchDir, clientBridge)
}
} else {

if gcd.GlobalSettings.PreviousPid != -1 {
// Todo: Check if there is an older version of the ACN running...
log.Debugf("checking to see if we shutdown the previous ACN (%v)", gcd.GlobalSettings.PreviousPid)

os2.CheckProcessAndKill(uint64(gcd.GlobalSettings.PreviousPid), "tor")
}

loadACN()
pid,err := the.ACN.GetPID()
if err == nil {
gcd.GlobalSettings.PreviousPid = int64(pid)
ui.WriteGlobalSettings(gcd.GlobalSettings)

} else {
log.Errorf("error fetching pid from ACN %v", err)
}

log.Infoln("Creating New App")
the.CwtchApp = libapp.NewApp(the.ACN, the.CwtchDir)

}

if !service {


Loading…
Cancel
Save