diff options
author | Ruben Pollan <meskio@sindominio.net> | 2018-06-08 10:26:58 +0200 |
---|---|---|
committer | Ruben Pollan <meskio@sindominio.net> | 2018-06-20 12:18:03 +0200 |
commit | fcc7514ec5f1b35068b1033d8ac4278c45043a80 (patch) | |
tree | 0ad4d5f4d650ab2a01879e4f31faedf848c39287 /bitmask | |
parent | 11094e0f58e1f28f5333a91f3c4129b56ad154e6 (diff) |
[feat] pure go bitmask vpn implemenation
- Resolves: #42
Diffstat (limited to 'bitmask')
-rw-r--r-- | bitmask/bitmask.go (renamed from bitmask/events.go) | 43 | ||||
-rw-r--r-- | bitmask/main.go | 161 | ||||
-rw-r--r-- | bitmask/vpn.go | 92 |
3 files changed, 11 insertions, 285 deletions
diff --git a/bitmask/events.go b/bitmask/bitmask.go index e97804c..f9b1cc9 100644 --- a/bitmask/events.go +++ b/bitmask/bitmask.go @@ -15,36 +15,15 @@ package bitmask -import ( - "log" - "net/http" -) - -const ( - statusEvent = "VPN_STATUS_CHANGED" -) - -func (b *Bitmask) eventsHandler() { - b.send("events", "register", statusEvent) - client := &http.Client{ - Timeout: 0, - } - for { - resJSON, err := send(b.apiToken, client, "events", "poll") - res, ok := resJSON.([]interface{}) - if err != nil || !ok || len(res) < 1 { - continue - } - event, ok := res[0].(string) - if !ok || event != statusEvent { - continue - } - - status, err := b.GetStatus() - if err != nil { - log.Printf("Error receiving status: %v", err) - continue - } - b.statusCh <- status - } +type Bitmask interface { + GetStatusCh() <-chan string + Close() + Version() (string, error) + StartVPN(provider string) error + StopVPN() error + GetStatus() (string, error) + InstallHelpers() error + VPNCheck() (helpers bool, priviledge bool, err error) + ListGateways(provider string) ([]string, error) + UseGateway(name string) error } diff --git a/bitmask/main.go b/bitmask/main.go deleted file mode 100644 index e0bf4a0..0000000 --- a/bitmask/main.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (C) 2018 LEAP -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -package bitmask - -import ( - "bytes" - "encoding/json" - "errors" - "io/ioutil" - "log" - "net/http" - "path" - "time" -) - -const ( - timeout = time.Second * 15 - url = "http://localhost:7070/API/" - headerAuth = "X-Bitmask-Auth" -) - -// Bitmask holds the bitmask client data -type Bitmask struct { - client *http.Client - apiToken string - statusCh chan string -} - -// Init the connection to bitmask -func Init() (*Bitmask, error) { - statusCh := make(chan string) - client := &http.Client{ - Timeout: timeout, - } - - err := waitForBitmaskd() - if err != nil { - return nil, err - } - - apiToken, err := getToken() - if err != nil { - return nil, err - } - - b := Bitmask{client, apiToken, statusCh} - go b.eventsHandler() - return &b, nil -} - -// GetStatusCh returns a channel that will recieve VPN status changes -func (b *Bitmask) GetStatusCh() chan string { - return b.statusCh -} - -// Close the connection to bitmask -func (b *Bitmask) Close() { - _, err := b.send("core", "stop") - if err != nil { - log.Printf("Got an error stopping bitmaskd: %v", err) - } -} - -// Version gets the bitmask version string -func (b *Bitmask) Version() (string, error) { - res, err := b.send("core", "version") - if err != nil { - return "", err - } - return res["version_core"].(string), nil -} - -func waitForBitmaskd() error { - var err error - for i := 0; i < 30; i++ { - resp, err := http.Post(url, "", nil) - if err == nil { - resp.Body.Close() - return nil - } - log.Printf("Bitmask is not ready (iteration %d): %v", i, err) - time.Sleep(1 * time.Second) - } - return err -} - -func (b *Bitmask) send(parts ...interface{}) (map[string]interface{}, error) { - resJSON, err := send(b.apiToken, b.client, parts...) - if err != nil { - return nil, err - } - result, ok := resJSON.(map[string]interface{}) - if !ok { - return nil, errors.New("Not valid response") - } - return result, nil -} - -func send(apiToken string, client *http.Client, parts ...interface{}) (interface{}, error) { - apiSection, _ := parts[0].(string) - reqBody, err := json.Marshal(parts[1:]) - if err != nil { - return nil, err - } - req, err := http.NewRequest("POST", url+apiSection, bytes.NewReader(reqBody)) - if err != nil { - return nil, err - } - req.Header.Add(headerAuth, apiToken) - - resp, err := client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - resJSON, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - return parseResponse(resJSON) -} - -func parseResponse(resJSON []byte) (interface{}, error) { - var response struct { - Result interface{} - Error string - } - err := json.Unmarshal(resJSON, &response) - if response.Error != "" { - return nil, errors.New(response.Error) - } - return response.Result, err -} - -func getToken() (string, error) { - var err error - path := path.Join(ConfigPath, "authtoken") - for i := 0; i < 30; i++ { - b, err := ioutil.ReadFile(path) - if err == nil { - return string(b), nil - } - log.Printf("Auth token is not ready (iteration %d): %v", i, err) - time.Sleep(1 * time.Second) - } - return "", err -} diff --git a/bitmask/vpn.go b/bitmask/vpn.go deleted file mode 100644 index aee5e8f..0000000 --- a/bitmask/vpn.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2018 LEAP -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -package bitmask - -import ( - "errors" - "log" -) - -// StartVPN for provider -func (b *Bitmask) StartVPN(provider string) error { - _, err := b.send("vpn", "start", provider) - return err -} - -// StopVPN or cancel -func (b *Bitmask) StopVPN() error { - _, err := b.send("vpn", "stop") - return err -} - -// GetStatus returns the VPN status -func (b *Bitmask) GetStatus() (string, error) { - res, err := b.send("vpn", "status") - if err != nil { - return "", err - } - return res["status"].(string), nil -} - -// InstallHelpers into the system -func (b *Bitmask) InstallHelpers() error { - _, err := b.send("vpn", "install") - return err -} - -// VPNCheck returns if the helpers are installed and up to date and if polkit is running -func (b *Bitmask) VPNCheck() (helpers bool, priviledge bool, err error) { - res, err := b.send("vpn", "check", "") - if err != nil { - return false, false, err - } - installed, ok := res["installed"].(bool) - if !ok { - log.Printf("Unexpected value for installed on 'vpn check': %v", res) - return false, false, errors.New("Invalid response format") - } - privcheck, ok := res["privcheck"].(bool) - if !ok { - log.Printf("Unexpected value for privcheck on 'vpn check': %v", res) - return installed, false, errors.New("Invalid response format") - } - return installed, privcheck, nil -} - -// ListGateways return the names of the gateways -func (b *Bitmask) ListGateways(provider string) ([]string, error) { - res, err := b.send("vpn", "list") - if err != nil { - return nil, err - } - - names := []string{} - locations, ok := res[provider].([]interface{}) - if !ok { - return nil, errors.New("Can't read the locations for provider " + provider) - } - for i := range locations { - loc := locations[i].(map[string]interface{}) - names = append(names, loc["name"].(string)) - } - return names, nil -} - -// UseGateway selects name as the default gateway -func (b *Bitmask) UseGateway(name string) error { - _, err := b.send("vpn", "locations", name) - return err -} |