From 9961c7ea6695551b97ee527ef905db32eeddd25a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Mon, 16 Mar 2020 19:26:03 +0200 Subject: [PATCH] Initial boilerplate to get some infra started --- README.md | 39 +++++++++++++++++++++++++++ backend.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bridge.go | 22 +++++++++++++++ go.mod | 12 +++++++++ go.sum | 26 ++++++++++++++++++ service.go | 14 ++++++++++ 6 files changed, 192 insertions(+) create mode 100644 README.md create mode 100644 backend.go create mode 100644 bridge.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 service.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..2595269 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +### How to build + +The Corona Network protocol is written in [Go](https://golang.org/). If you want to contribute to this part of the code, you need to have a valid Go installation. We are also using [Go modules](https://blog.golang.org/using-go-modules), please familiarize yourself with them if they are new to you. You will also need a C compiler as certain dependencies of this project are in C. + +If you can run `go install` in the repo root successfully, you're halfway there! + +Go is one prerequisite, but it's not the only one. The main platform we are aiming for are mobile phones, so this project also needs to compile to them. We use [`gomobile`](https://github.com/golang/mobile/) to create the library archives that can be imported into mobile projects. You do not need to be familiar with `gomobile`, but you need to be able to run it. + +You can install `gomobile` via: + +``` +$ go get -u golang.org/x/mobile/cmd/gomobile +$ go get -u golang.org/x/mobile/cmd/gobind +``` + +#### Android + +To build the Android library archive (`.aar`), you need to have an Android SDK and NDK installed and the `ANDROID_HOME` environment var correctly set. Please consult the Android docs if you're stuck. You might want to do it through [Android Studio](https://developer.android.com/studio). We're not going to use the Android Studio at all, but it's an easy way to manage your SDKs and Android emulators. + +Once Android is configured, you can build `go-coronanet` via: + +``` +$ gomobile bind --target android --javapkg xyz -v github.com/coronanet/go-coronanet +``` + +The first time you do the above, it will take a **LOT** of time. I'm not kidding, on the order of **30 minutes**, as it needs to build some humongous C dependencies for 4 different architectures (x86, x86_64, arm, arm64). The good news is that subsequent builds will be fast(er). + +``` +$ ls -al | grep coronanet + +-rw-r--r-- 1 karalabe karalabe 46961891 Mar 16 19:19 coronanet.aar +-rw-r--r-- 1 karalabe karalabe 6383 Mar 16 19:19 coronanet-sources.jar +``` + +Whoa, that final binary size is insane. Yes it is, but it does contain 4 architectures + debug symbols. Long term a proper build system could make things a bit more pleasant. Optimizing app size is not relevant at this phase, simplicity and portability are more useful. + +#### iOS + +iOS is not planned for the initial MVP to keep the scope smaller. A lot of prerequisite work needs to be done on supporting infra first (`libtor`, `ghostbridge`, etc), which is wasted time until it's proven to be worth it. diff --git a/backend.go b/backend.go new file mode 100644 index 0000000..3861f8c --- /dev/null +++ b/backend.go @@ -0,0 +1,79 @@ +// coronanet - Coronavirus social distancing network +// Copyright (c) 2020 Péter Szilágyi. All rights reserved. + +package coronanet + +import ( + "fmt" + "sync" + + "github.com/cretz/bine/tor" + "github.com/ipsn/go-libtor" +) + +// backend represents the social network node that can connect to other nodes in +// the network and exchange information. +type backend struct { + proxy *tor.Tor // Proxy through the Tor network, nil when offline + + lock sync.RWMutex +} + +// newBackend creates a new social network node. +func newBackend() (*backend, error) { + return &backend{}, nil +} + +// Enable creates the network proxy into the Tor network. +func (b *backend) Enable() error { + // Ensure the node is not yet enabled + b.lock.Lock() + defer b.lock.Unlock() + + if b.proxy != nil { + return nil + } + // Create the Tor background process and let it bootstrap itself async. + proxy, err := tor.Start(nil, &tor.StartConf{ProcessCreator: libtor.Creator, UseEmbeddedControlConn: true}) + if err != nil { + return err + } + b.proxy = proxy + return nil +} + +// Disable stops and tears down the network proxy into the Tor network. +func (b *backend) Disable() error { + // Ensure the node is not yet disabled + b.lock.Lock() + defer b.lock.Unlock() + + if b.proxy == nil { + return nil + } + // Proxy still functional, terminate it and return + if err := b.proxy.Close(); err != nil { + return err + } + b.proxy = nil + return nil +} + +// Status returns whether the backend has networking enabled and the total down- +// and upload traffic incurred since starting it. +func (b *backend) Status() (bool, uint64, uint64, error) { + // If the node is offline, return all zeroes + b.lock.RLock() + defer b.lock.RUnlock() + + if b.proxy == nil { + return false, 0, 0, nil + } + // Tor proxy online, retrieve the current stats + res, err := b.proxy.Control.GetInfo("traffic/read", "traffic/written") + if err != nil { + return true, 0, 0, err + } + fmt.Println(res[0].Val, res[1].Val) + return true, 0, 0, nil +} diff --git a/bridge.go b/bridge.go new file mode 100644 index 0000000..b9cad9c --- /dev/null +++ b/bridge.go @@ -0,0 +1,22 @@ +// coronanet - Coronavirus social distancing network +// Copyright (c) 2020 Péter Szilágyi. All rights reserved. + +package coronanet + +import "github.com/ipsn/go-ghostbridge" + +// Bridge is a tiny struct (re)definition so gomobile will export all the built +// in methods of the underlying ghostbridge.Bridge struct. +type Bridge struct { + *ghostbridge.Bridge +} + +// NewBridge creates an instance of the ghost bridge, typed such as gomobile to +// generate a Bridge constructor out of it. +func NewBridge() (*Bridge, error) { + bridge, err := ghostbridge.New(new(backend)) + if err != nil { + return nil, err + } + return &Bridge{bridge}, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3530337 --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module github.com/coronanet/go-coronanet + +go 1.14 + +require ( + github.com/cretz/bine v0.1.0 + github.com/ipsn/go-ghostbridge v0.0.0-20190304084428-78924eea6711 + github.com/ipsn/go-libtor v1.0.196 + golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 // indirect + golang.org/x/net v0.0.0-20200301022130-244492dfa37a // indirect + golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a05b0d9 --- /dev/null +++ b/go.sum @@ -0,0 +1,26 @@ +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/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/ipsn/go-ghostbridge v0.0.0-20190304084428-78924eea6711 h1:H4ciRFuWzihulBvcHmP+M0EksEqgAPApebL1aSA4r4o= +github.com/ipsn/go-ghostbridge v0.0.0-20190304084428-78924eea6711/go.mod h1:hxUrR1DTnI1KNaGWoF/ZEM8dmu1aP454LeMXLZ5KmrM= +github.com/ipsn/go-libtor v1.0.196 h1:MrGPdIXyGdTPItZwqtfI12dEES7nF6IlghbGKM2GCBQ= +github.com/ipsn/go-libtor v1.0.196/go.mod h1:6rIeHU7irp8ZH8E/JqaEOKlD6s4vSSUh4ngHelhlSMw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/service.go b/service.go new file mode 100644 index 0000000..951f5aa --- /dev/null +++ b/service.go @@ -0,0 +1,14 @@ +// coronanet - Coronavirus social distancing network +// Copyright (c) 2020 Péter Szilágyi. All rights reserved. + +package coronanet + +import ( + "net/http" +) + +// ServeHTTP implements http.Handler, serving API calls from the mobile UI. It +// exposes all the functionality of the social network via a RESTful interface +// for react native on a mobile. +func (b *backend) ServeHTTP(w http.ResponseWriter, r *http.Request) { +}