Commit 76cacf3d authored by Kali Kaneko's avatar Kali Kaneko
Browse files

wip: select by city from the gui

parent 8d616ba5
......@@ -4,10 +4,8 @@ import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.4
//import QtQuick.Extras 1.2
import Qt.labs.platform 1.0
//as LabsPlatform
Window {
id: app
visible: true
......@@ -90,6 +88,7 @@ Window {
target: jsonModel
onDataChanged: {
ctx = JSON.parse(jsonModel.getJson())
console.debug(jsonModel.getJson())
gwSelector.model = Object.keys(ctx.gateways)
if (ctx.donateDialog == 'true') {
......@@ -277,29 +276,6 @@ Window {
/* a minimal segfault for submenu */
// Menu {}
/* this segfaults too (but it's the way to do dynamic item creation */
/*
Menu {
id: manualGatewaysSubmenu
title: qsTr("Manual Gateways")
enabled: true
Instantiator {
id: manualGatewayInstantiator
//model: settings.recentFiles
delegate: MenuItem {
text: "test gateway"
}
onObjectAdded: manualGatewaysSubmenu.insertItem(index, object)
onObjectRemoved: manualGatewaysSubmenu.removeItem(object)
}
MenuSeparator {}
}
*/
MenuSeparator {}
MenuItem {
......
......@@ -33,33 +33,36 @@ var updateMutex sync.Mutex
// them.
type connectionCtx struct {
AppName string `json:"appName"`
Provider string `json:"provider"`
TosURL string `json:"tosURL"`
HelpURL string `json:"helpURL"`
AskForDonations bool `json:"askForDonations"`
DonateDialog bool `json:"donateDialog"`
DonateURL string `json:"donateURL"`
LoginDialog bool `json:"loginDialog"`
LoginOk bool `json:"loginOk"`
Version string `json:"version"`
Errors string `json:"errors"`
Status status `json:"status"`
Gateways map[string]bonafide.Gateway `json:"gateways"`
CurrentGateway string `json:"currentGateway"`
bm bitmask.Bitmask
autostart bitmask.Autostart
cfg *config.Config
AppName string `json:"appName"`
Provider string `json:"provider"`
TosURL string `json:"tosURL"`
HelpURL string `json:"helpURL"`
AskForDonations bool `json:"askForDonations"`
DonateDialog bool `json:"donateDialog"`
DonateURL string `json:"donateURL"`
LoginDialog bool `json:"loginDialog"`
LoginOk bool `json:"loginOk"`
Version string `json:"version"`
Errors string `json:"errors"`
Status status `json:"status"`
/* XXX rename to GatewaysByCity */
Gateways map[string]bonafide.Gateway `json:"gateways"`
CurrentGateway string `json:"currentGateway"`
bm bitmask.Bitmask
autostart bitmask.Autostart
cfg *config.Config
}
func (c connectionCtx) toJson() ([]byte, error) {
statusMutex.Lock()
if c.bm != nil {
c.Gateways = map[string]bonafide.Gateway{}
gateways, _ := c.bm.ListGateways("openvpn")
for _, label := range gateways {
gw, _ := c.bm.GetGatewayDetails(label)
c.Gateways[label] = gw.(bonafide.Gateway)
/* FIXME this returns hostnames, could return bonafide gateway directly */
gateways, _ := c.bm.ListGatewaysByCity("openvpn")
log.Println(">>> got gws for cities", gateways)
for city, host := range gateways {
gw, _ := c.bm.GetGatewayDetails(host)
c.Gateways[city] = gw.(bonafide.Gateway)
}
c.CurrentGateway = c.bm.GetCurrentGateway()
}
......
......@@ -64,9 +64,9 @@ func webGatewaySet(w http.ResponseWriter, r *http.Request) {
}
func webGatewayList(w http.ResponseWriter, r *http.Request) {
gws, err := ctx.bm.ListGateways(ctx.Provider)
gws, err := ctx.bm.ListGatewaysByCity(ctx.Provider)
if err != nil {
fmt.Fprintf(w, "ListGateways() err: %v", err)
fmt.Fprintf(w, "ListGatewaysByCity() err: %v", err)
}
gwJson, _ := json.Marshal(gws)
fmt.Fprintf(w, string(gwJson))
......
......@@ -26,7 +26,7 @@ type Bitmask interface {
GetStatus() (string, error)
InstallHelpers() error
VPNCheck() (helpers bool, priviledge bool, err error)
ListGateways(provider string) ([]string, error)
ListGatewaysByCity(provider string) (map[string]string, error)
UseGateway(name string) error
GetCurrentGateway() string
GetGatewayDetails(label string) (interface{}, error)
......
......@@ -192,7 +192,7 @@ func (b *Bonafide) maybeInitializeEIP() error {
return err
}
b.gateways = newGatewayPool(b.eip)
b.fetchGatewayRanking()
b.fetchGatewaysFromMenshen()
}
return nil
}
......@@ -224,8 +224,13 @@ func (b *Bonafide) GetAllGateways(transport string) ([]Gateway, error) {
return gws, err
}
func (b *Bonafide) GetGatewayDetails(label string) (Gateway, error) {
return b.gateways.getGatewayByLabel(label)
func (b *Bonafide) PickGatewayForCities() (map[string]string, error) {
return b.gateways.pickGatewayForCities(), nil
}
func (b *Bonafide) GetGatewayDetails(host string) (Gateway, error) {
gw, err := b.gateways.getGatewayByHost(host)
return gw, err
}
func (b *Bonafide) SetManualGateway(label string) {
......@@ -241,7 +246,7 @@ func (b *Bonafide) GetGatewayByIP(ip string) (Gateway, error) {
}
/* TODO this still needs to be called periodically */
func (b *Bonafide) fetchGatewayRanking() error {
func (b *Bonafide) fetchGatewaysFromMenshen() error {
/* FIXME in float deployments, geolocation is served on gemyip.domain/json, with a LE certificate, but in riseup is served behind the api certificate.
So this is a workaround until we streamline that behavior */
resp, err := b.client.Post(config.GeolocationAPI, "", nil)
......@@ -272,7 +277,7 @@ func (b *Bonafide) fetchGatewayRanking() error {
}
log.Println("Got sorted gateways:", geo.SortedGateways)
b.gateways.setRanking(geo.SortedGateways)
b.gateways.setRecommendedGateways(geo.SortedGateways)
return nil
}
......
......@@ -33,27 +33,24 @@ type Load struct {
Fullness string
}
type gatewayDistance struct {
gateway Gateway
distance int
}
/* a map between locations and hostnames, to be able to select by city */
type cityMap struct {
gws map[string][]string
}
/*
func (g *cityMap) Get(key string) []string {
if val, ok := g.gws[key]; ok {
return val
}
return make([]string, 0)
}
*/
/* gatewayDistance is used in the timezone distance fallback */
type gatewayDistance struct {
gateway Gateway
distance int
}
type gatewayPool struct {
available []Gateway
userChoice []byte
byCity cityMap
byCity map[string][]string
/* recommended is an array of hostnames, fetched from the old geoip service.
* this should be deprecated in favor of recommendedWithLoad when new menshen is deployed */
......@@ -70,9 +67,14 @@ type gatewayPool struct {
func (p *gatewayPool) populateCityList() {
for _, gw := range p.available {
loc := gw.Location
gws := p.cityMap.Get(loc)
p.cityMap[loc] = append(gws, gw.Host)
gws := p.byCity[loc]
if len(gws) == 0 {
p.byCity[loc] = []string{gw.Host}
} else {
p.byCity[loc] = append(gws, gw.Host)
}
}
log.Println(p.byCity)
}
func (p *gatewayPool) getCities() []string {
......@@ -89,12 +91,23 @@ func (p *gatewayPool) isValidCity(city string) bool {
return valid
}
/* returns a map of city: hostname for the ui to use */
func (p *gatewayPool) pickGatewayForCities() map[string]string {
cities := p.getCities()
cm := make(map[string]string)
for _, city := range cities {
gw, _ := p.getRandomGatewayByCity(city)
cm[city] = gw.Host
}
return cm
}
/* this method should only be used if we have no usable menshen list */
func (p *gatewayPool) getRandomGatewayByCity(city string) (Gateway, error) {
if !p.isValidCity(city) {
return Gateway{}, errors.New("bonafide: BUG not a valid city: " + city)
}
gws := p.byCity.Get(city)
gws := p.byCity[city]
if len(gws) == 0 {
return Gateway{}, errors.New("bonafide: BUG no gw for city " + city)
}
......@@ -109,54 +122,14 @@ func (p *gatewayPool) getRandomGatewayByCity(city string) (Gateway, error) {
return Gateway{}, errors.New("bonafide: BUG should not reach here")
}
/* genLabels generates unique, human-readable labels for a gateway. It gives a serial
number to each gateway in the same location (paris-1, paris-2,...). The
current implementation will give a different label to each transport.
An alternative (to discuss) would be to give the same label to the same hostname.
func (p *gatewayPool) genLabels() {
acc := make(map[string]int)
for i, gw := range p.available {
if _, count := acc[gw.Location]; !count {
acc[gw.Location] = 1
} else {
acc[gw.Location] += 1
}
gw.Label = gw.Location + "-" + strconv.Itoa(acc[gw.Location])
p.available[i] = gw
}
for i, gw := range p.available {
if acc[gw.Location] == 1 {
gw.Label = gw.Location
p.available[i] = gw
}
}
}
*/
/*
func (p *gatewayPool) getLabels() []string {
labels := make([]string, 0)
func (p *gatewayPool) getGatewayByHost(host string) (Gateway, error) {
for _, gw := range p.available {
labels = append(labels, gw.Label)
}
return labels
}
func (p *gatewayPool) isValidLabel(label string) bool {
labels := p.getLabels()
valid := stringInSlice(label, labels)
return valid
}
func (p *gatewayPool) getGatewayByLabel(label string) (Gateway, error) {
for _, gw := range p.available {
if gw.Label == label {
if gw.Host == host {
return gw, nil
}
}
return Gateway{}, errors.New("bonafide: not a valid label")
return Gateway{}, errors.New("bonafide: not a valid host name")
}
*/
func (p *gatewayPool) getGatewayByIP(ip string) (Gateway, error) {
for _, gw := range p.available {
......@@ -179,7 +152,7 @@ func (p *gatewayPool) setUserChoice(city []byte) error {
return nil
}
func (p *gatewayPool) setRanking(hostnames []string) {
func (p *gatewayPool) setRecommendedGateways(hostnames []string) {
hosts := make([]string, 0)
for _, gw := range p.available {
hosts = append(hosts, gw.Host)
......@@ -277,6 +250,7 @@ func newGatewayPool(eip *eipService) *gatewayPool {
p := gatewayPool{}
p.available = eip.getGateways()
p.locations = eip.Locations
p.byCity = make(map[string][]string, 0)
p.populateCityList()
return &p
}
......
......@@ -231,22 +231,14 @@ func (b *Bitmask) VPNCheck() (helpers bool, privilege bool, err error) {
return b.launch.check()
}
// ListGateways return the labels of the gateways (only for transport=openvpn, at the moment)
// TODO return other transports too
func (b *Bitmask) ListGateways(provider string) ([]string, error) {
gateways, err := b.bonafide.GetAllGateways("openvpn")
if err != nil {
return nil, err
}
gatewayNames := make([]string, len(gateways))
for i, gw := range gateways {
gatewayNames[i] = gw.Label
}
return gatewayNames, nil
func (b *Bitmask) ListGatewaysByCity(transport string) (map[string]string, error) {
/* TODO filter by transport */
gwForCities, err := b.bonafide.PickGatewayForCities()
return gwForCities, err
}
func (b *Bitmask) GetGatewayDetails(label string) (interface{}, error) {
gw, err := b.bonafide.GetGatewayDetails(label)
func (b *Bitmask) GetGatewayDetails(host string) (interface{}, error) {
gw, err := b.bonafide.GetGatewayDetails(host)
if err != nil {
return bonafide.Gateway{}, err
}
......
......@@ -77,7 +77,7 @@ func (b *Bitmask) eventHandler(eventCh <-chan openvpn.Event) {
gw, err := b.bonafide.GetGatewayByIP(ip)
if err == nil {
b.onGateway = gw
log.Println("Connected to gateway:", b.onGateway.Label)
log.Println("Connected to gateway:", b.onGateway.Host)
} else {
log.Println("ERROR: connected to unknown gateway", ip)
}
......@@ -87,7 +87,7 @@ func (b *Bitmask) eventHandler(eventCh <-chan openvpn.Event) {
}
func (b *Bitmask) GetCurrentGateway() string {
return b.onGateway.Label
return b.onGateway.Host
}
func (b *Bitmask) getOpenvpnState() (string, error) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment