mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 20:56:51 +00:00
89 lines
2.8 KiB
Go
89 lines
2.8 KiB
Go
// Copyright (c) 2020 Proton Technologies AG
|
|
//
|
|
// This file is part of ProtonMail Bridge.
|
|
//
|
|
// ProtonMail Bridge 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.
|
|
//
|
|
// ProtonMail Bridge 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package connection
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/ProtonMail/proton-bridge/pkg/config"
|
|
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
|
)
|
|
|
|
// Errors for possible connection issues
|
|
var (
|
|
ErrNoInternetConnection = errors.New("no internet connection")
|
|
ErrCanNotReachAPI = errors.New("can not reach PM API")
|
|
log = config.GetLogEntry("connection") //nolint[gochecknoglobals]
|
|
)
|
|
|
|
// CheckInternetConnection does a check of API connection. It checks two of our endpoints in parallel.
|
|
// One endpoint is part of the protonmail API, while the other is not.
|
|
// This allows us to determine whether there is a problem with the connection itself or only a problem with our API.
|
|
// Two errors can be returned, ErrNoInternetConnection or ErrCanNotReachAPI.
|
|
func CheckInternetConnection() error {
|
|
client := &http.Client{
|
|
Transport: pmapi.NewPMAPIPinning(pmapi.CurrentUserAgent).TransportWithPinning(),
|
|
}
|
|
|
|
// Do not cumulate timeouts, use goroutines.
|
|
retStatus := make(chan error)
|
|
retAPI := make(chan error)
|
|
|
|
// Check protonstatus.com without SSL for performance reasons. vpn_status endpoint is fast and
|
|
// returns only OK; this endpoint is not known by the public. We check the connection only.
|
|
go checkConnection(client, "http://protonstatus.com/vpn_status", retStatus)
|
|
|
|
// Check of API reachability also uses a fast endpoint.
|
|
go checkConnection(client, pmapi.GlobalGetRootURL()+"/tests/ping", retAPI)
|
|
|
|
errStatus := <-retStatus
|
|
errAPI := <-retAPI
|
|
|
|
if errStatus != nil {
|
|
if errAPI != nil {
|
|
log.Error("Checking internet connection failed with ", errStatus, " and ", errAPI)
|
|
return ErrNoInternetConnection
|
|
}
|
|
log.Warning("API OK, but status: ", errStatus)
|
|
return nil
|
|
}
|
|
|
|
if errAPI != nil {
|
|
log.Error("Status OK, but API: ", errAPI)
|
|
return ErrCanNotReachAPI
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func checkConnection(client *http.Client, url string, errorChannel chan error) {
|
|
resp, err := client.Get(url)
|
|
if err != nil {
|
|
errorChannel <- err
|
|
return
|
|
}
|
|
_ = resp.Body.Close()
|
|
if resp.StatusCode != 200 {
|
|
errorChannel <- fmt.Errorf("HTTP status code %d", resp.StatusCode)
|
|
return
|
|
}
|
|
errorChannel <- nil
|
|
}
|