2021-02-02 12:05:47 +01:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/atomicx"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/geolocate"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/internal/platform"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/internal/sessionresolver"
|
2021-02-04 11:00:27 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/kvstore"
|
2021-02-02 12:05:47 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/bytecounter"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/probeservices"
|
2021-04-03 19:57:21 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/tunnel"
|
2021-02-04 11:00:27 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/version"
|
2021-02-02 12:05:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// SessionConfig contains the Session config
|
|
|
|
type SessionConfig struct {
|
|
|
|
AvailableProbeServices []model.Service
|
|
|
|
KVStore KVStore
|
|
|
|
Logger model.Logger
|
|
|
|
ProxyURL *url.URL
|
|
|
|
SoftwareName string
|
|
|
|
SoftwareVersion string
|
|
|
|
TempDir string
|
|
|
|
TorArgs []string
|
|
|
|
TorBinary string
|
2021-04-05 11:27:41 +02:00
|
|
|
|
|
|
|
// TunnelDir is the directory where we should store
|
|
|
|
// the state of persistent tunnels. This field is
|
|
|
|
// optional _unless_ you want to use tunnels. In such
|
|
|
|
// case, starting a tunnel will fail because there
|
|
|
|
// is no directory where to store state.
|
|
|
|
TunnelDir string
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
2021-04-01 16:57:31 +02:00
|
|
|
// Session is a measurement session. It contains shared information
|
|
|
|
// required to run a measurement session, and it controls the lifecycle
|
|
|
|
// of such resources. It is not possible to reuse a Session. You MUST
|
|
|
|
// NOT attempt to use a Session again after Session.Close.
|
2021-02-02 12:05:47 +01:00
|
|
|
type Session struct {
|
|
|
|
availableProbeServices []model.Service
|
|
|
|
availableTestHelpers map[string][]model.Service
|
|
|
|
byteCounter *bytecounter.Counter
|
|
|
|
httpDefaultTransport netx.HTTPRoundTripper
|
|
|
|
kvStore model.KeyValueStore
|
|
|
|
location *geolocate.Results
|
|
|
|
logger model.Logger
|
|
|
|
proxyURL *url.URL
|
|
|
|
queryProbeServicesCount *atomicx.Int64
|
|
|
|
resolver *sessionresolver.Resolver
|
|
|
|
selectedProbeServiceHook func(*model.Service)
|
|
|
|
selectedProbeService *model.Service
|
|
|
|
softwareName string
|
|
|
|
softwareVersion string
|
|
|
|
tempDir string
|
|
|
|
torArgs []string
|
|
|
|
torBinary string
|
2021-04-05 11:27:41 +02:00
|
|
|
tunnelDir string
|
2021-02-02 12:05:47 +01:00
|
|
|
tunnelMu sync.Mutex
|
|
|
|
tunnelName string
|
|
|
|
tunnel tunnel.Tunnel
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
|
2021-04-01 16:57:31 +02:00
|
|
|
// closeOnce allows us to call Close just once.
|
|
|
|
closeOnce sync.Once
|
|
|
|
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// mu provides mutual exclusion.
|
|
|
|
mu sync.Mutex
|
|
|
|
|
|
|
|
// testLookupLocationContext is a an optional hook for testing
|
|
|
|
// allowing us to mock LookupLocationContext.
|
|
|
|
testLookupLocationContext func(ctx context.Context) (*geolocate.Results, error)
|
|
|
|
|
|
|
|
// testMaybeLookupBackendsContext is an optional hook for testing
|
|
|
|
// allowing us to mock MaybeLookupBackendsContext.
|
|
|
|
testMaybeLookupBackendsContext func(ctx context.Context) error
|
|
|
|
|
|
|
|
// testMaybeLookupLocationContext is an optional hook for testing
|
|
|
|
// allowing us to mock MaybeLookupLocationContext.
|
|
|
|
testMaybeLookupLocationContext func(ctx context.Context) error
|
|
|
|
|
|
|
|
// testNewProbeServicesClientForCheckIn is an optional hook for testing
|
|
|
|
// allowing us to mock NewProbeServicesClient when calling CheckIn.
|
|
|
|
testNewProbeServicesClientForCheckIn func(ctx context.Context) (
|
|
|
|
sessionProbeServicesClientForCheckIn, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// sessionProbeServicesClientForCheckIn returns the probe services
|
|
|
|
// client that we should be using for performing the check-in.
|
|
|
|
type sessionProbeServicesClientForCheckIn interface {
|
|
|
|
CheckIn(ctx context.Context, config model.CheckInConfig) (*model.CheckInInfo, error)
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewSession creates a new session or returns an error
|
|
|
|
func NewSession(config SessionConfig) (*Session, error) {
|
|
|
|
if config.Logger == nil {
|
|
|
|
return nil, errors.New("Logger is empty")
|
|
|
|
}
|
|
|
|
if config.SoftwareName == "" {
|
|
|
|
return nil, errors.New("SoftwareName is empty")
|
|
|
|
}
|
|
|
|
if config.SoftwareVersion == "" {
|
|
|
|
return nil, errors.New("SoftwareVersion is empty")
|
|
|
|
}
|
|
|
|
if config.KVStore == nil {
|
|
|
|
config.KVStore = kvstore.NewMemoryKeyValueStore()
|
|
|
|
}
|
|
|
|
// Implementation note: if config.TempDir is empty, then Go will
|
|
|
|
// use the temporary directory on the current system. This should
|
|
|
|
// work on Desktop. We tested that it did also work on iOS, but
|
|
|
|
// we have also seen on 2020-06-10 that it does not work on Android.
|
|
|
|
tempDir, err := ioutil.TempDir(config.TempDir, "ooniengine")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
sess := &Session{
|
|
|
|
availableProbeServices: config.AvailableProbeServices,
|
|
|
|
byteCounter: bytecounter.New(),
|
|
|
|
kvStore: config.KVStore,
|
|
|
|
logger: config.Logger,
|
|
|
|
proxyURL: config.ProxyURL,
|
|
|
|
queryProbeServicesCount: atomicx.NewInt64(),
|
|
|
|
softwareName: config.SoftwareName,
|
|
|
|
softwareVersion: config.SoftwareVersion,
|
|
|
|
tempDir: tempDir,
|
|
|
|
torArgs: config.TorArgs,
|
|
|
|
torBinary: config.TorBinary,
|
2021-04-05 11:27:41 +02:00
|
|
|
tunnelDir: config.TunnelDir,
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
httpConfig := netx.Config{
|
|
|
|
ByteCounter: sess.byteCounter,
|
|
|
|
BogonIsError: true,
|
|
|
|
Logger: sess.logger,
|
2021-03-10 10:39:57 +01:00
|
|
|
ProxyURL: config.ProxyURL,
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
2021-03-03 11:28:39 +01:00
|
|
|
sess.resolver = &sessionresolver.Resolver{
|
|
|
|
ByteCounter: sess.byteCounter,
|
|
|
|
KVStore: config.KVStore,
|
|
|
|
Logger: sess.logger,
|
2021-03-10 10:39:57 +01:00
|
|
|
ProxyURL: config.ProxyURL,
|
2021-03-03 11:28:39 +01:00
|
|
|
}
|
2021-02-02 12:05:47 +01:00
|
|
|
httpConfig.FullResolver = sess.resolver
|
|
|
|
sess.httpDefaultTransport = netx.NewHTTPTransport(httpConfig)
|
|
|
|
return sess, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// KibiBytesReceived accounts for the KibiBytes received by the HTTP clients
|
|
|
|
// managed by this session so far, including experiments.
|
|
|
|
func (s *Session) KibiBytesReceived() float64 {
|
|
|
|
return s.byteCounter.KibiBytesReceived()
|
|
|
|
}
|
|
|
|
|
|
|
|
// KibiBytesSent is like KibiBytesReceived but for the bytes sent.
|
|
|
|
func (s *Session) KibiBytesSent() float64 {
|
|
|
|
return s.byteCounter.KibiBytesSent()
|
|
|
|
}
|
|
|
|
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// CheckIn calls the check-in API. The input arguments MUST NOT
|
|
|
|
// be nil. Before querying the API, this function will ensure
|
|
|
|
// that the config structure does not contain any field that
|
|
|
|
// SHOULD be initialized and is not initialized. Whenever there
|
|
|
|
// is a field that is not initialized, we will attempt to set
|
|
|
|
// a reasonable default value for such a field. This list describes
|
|
|
|
// the current defaults we'll choose:
|
|
|
|
//
|
|
|
|
// - Platform: if empty, set to Session.Platform();
|
|
|
|
//
|
|
|
|
// - ProbeASN: if empty, set to Session.ProbeASNString();
|
|
|
|
//
|
|
|
|
// - ProbeCC: if empty, set to Session.ProbeCC();
|
|
|
|
//
|
|
|
|
// - RunType: if empty, set to "timed";
|
|
|
|
//
|
|
|
|
// - SoftwareName: if empty, set to Session.SoftwareName();
|
|
|
|
//
|
|
|
|
// - SoftwareVersion: if empty, set to Session.SoftwareVersion();
|
|
|
|
//
|
|
|
|
// - WebConnectivity.CategoryCodes: if nil, we will allocate
|
|
|
|
// an empty array (the API does not like nil).
|
|
|
|
//
|
|
|
|
// Because we MAY need to know the current ASN and CC, this
|
|
|
|
// function MAY call MaybeLookupLocationContext.
|
|
|
|
//
|
|
|
|
// The return value is either the check-in response or an error.
|
|
|
|
func (s *Session) CheckIn(
|
|
|
|
ctx context.Context, config *model.CheckInConfig) (*model.CheckInInfo, error) {
|
|
|
|
if err := s.maybeLookupLocationContext(ctx); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
client, err := s.newProbeServicesClientForCheckIn(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if config.Platform == "" {
|
|
|
|
config.Platform = s.Platform()
|
|
|
|
}
|
|
|
|
if config.ProbeASN == "" {
|
|
|
|
config.ProbeASN = s.ProbeASNString()
|
|
|
|
}
|
|
|
|
if config.ProbeCC == "" {
|
|
|
|
config.ProbeCC = s.ProbeCC()
|
|
|
|
}
|
|
|
|
if config.RunType == "" {
|
|
|
|
config.RunType = "timed" // most conservative choice
|
|
|
|
}
|
|
|
|
if config.SoftwareName == "" {
|
|
|
|
config.SoftwareName = s.SoftwareName()
|
|
|
|
}
|
|
|
|
if config.SoftwareVersion == "" {
|
|
|
|
config.SoftwareVersion = s.SoftwareVersion()
|
|
|
|
}
|
|
|
|
if config.WebConnectivity.CategoryCodes == nil {
|
|
|
|
config.WebConnectivity.CategoryCodes = []string{}
|
|
|
|
}
|
|
|
|
return client.CheckIn(ctx, *config)
|
|
|
|
}
|
|
|
|
|
|
|
|
// maybeLookupLocationContext is a wrapper for MaybeLookupLocationContext that calls
|
|
|
|
// the configurable testMaybeLookupLocationContext mock, if configured, and the
|
|
|
|
// real MaybeLookupLocationContext API otherwise.
|
|
|
|
func (s *Session) maybeLookupLocationContext(ctx context.Context) error {
|
|
|
|
if s.testMaybeLookupLocationContext != nil {
|
|
|
|
return s.testMaybeLookupLocationContext(ctx)
|
|
|
|
}
|
|
|
|
return s.MaybeLookupLocationContext(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
// newProbeServicesClientForCheckIn is a wrapper for NewProbeServicesClientForCheckIn
|
|
|
|
// that calls the configurable testNewProbeServicesClientForCheckIn mock, if
|
|
|
|
// configured, and the real NewProbeServicesClient API otherwise.
|
|
|
|
func (s *Session) newProbeServicesClientForCheckIn(
|
|
|
|
ctx context.Context) (sessionProbeServicesClientForCheckIn, error) {
|
|
|
|
if s.testNewProbeServicesClientForCheckIn != nil {
|
|
|
|
return s.testNewProbeServicesClientForCheckIn(ctx)
|
|
|
|
}
|
|
|
|
client, err := s.NewProbeServicesClient(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return client, nil
|
|
|
|
}
|
|
|
|
|
2021-02-02 12:05:47 +01:00
|
|
|
// Close ensures that we close all the idle connections that the HTTP clients
|
|
|
|
// we are currently using may have created. It will also remove the temp dir
|
|
|
|
// that contains data from this session. Not calling this function may likely
|
|
|
|
// cause memory leaks in your application because of open idle connections,
|
|
|
|
// as well as excessive usage of disk space.
|
|
|
|
func (s *Session) Close() error {
|
2021-04-01 16:57:31 +02:00
|
|
|
s.closeOnce.Do(s.doClose)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// doClose implements Close. This function is called just once.
|
|
|
|
func (s *Session) doClose() {
|
2021-02-02 12:05:47 +01:00
|
|
|
s.httpDefaultTransport.CloseIdleConnections()
|
|
|
|
s.resolver.CloseIdleConnections()
|
|
|
|
s.logger.Infof("%s", s.resolver.Stats())
|
|
|
|
if s.tunnel != nil {
|
|
|
|
s.tunnel.Stop()
|
|
|
|
}
|
2021-04-01 16:57:31 +02:00
|
|
|
_ = os.RemoveAll(s.tempDir)
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetTestHelpersByName returns the available test helpers that
|
|
|
|
// use the specified name, or false if there's none.
|
|
|
|
func (s *Session) GetTestHelpersByName(name string) ([]model.Service, bool) {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
services, ok := s.availableTestHelpers[name]
|
|
|
|
return services, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
// DefaultHTTPClient returns the session's default HTTP client.
|
|
|
|
func (s *Session) DefaultHTTPClient() *http.Client {
|
|
|
|
return &http.Client{Transport: s.httpDefaultTransport}
|
|
|
|
}
|
|
|
|
|
2021-04-02 12:03:18 +02:00
|
|
|
// FetchTorTargets fetches tor targets from the API.
|
|
|
|
func (s *Session) FetchTorTargets(
|
|
|
|
ctx context.Context, cc string) (map[string]model.TorTarget, error) {
|
|
|
|
clnt, err := s.NewOrchestraClient(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return clnt.FetchTorTargets(ctx, cc)
|
|
|
|
}
|
|
|
|
|
|
|
|
// FetchURLList fetches the URL list from the API.
|
|
|
|
func (s *Session) FetchURLList(
|
|
|
|
ctx context.Context, config model.URLListConfig) ([]model.URLInfo, error) {
|
|
|
|
clnt, err := s.NewOrchestraClient(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return clnt.FetchURLList(ctx, config)
|
|
|
|
}
|
|
|
|
|
2021-02-02 12:05:47 +01:00
|
|
|
// KeyValueStore returns the configured key-value store.
|
|
|
|
func (s *Session) KeyValueStore() model.KeyValueStore {
|
|
|
|
return s.kvStore
|
|
|
|
}
|
|
|
|
|
|
|
|
// Logger returns the logger used by the session.
|
|
|
|
func (s *Session) Logger() model.Logger {
|
|
|
|
return s.logger
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeLookupLocation is a caching location lookup call.
|
|
|
|
func (s *Session) MaybeLookupLocation() error {
|
|
|
|
return s.MaybeLookupLocationContext(context.Background())
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeLookupBackends is a caching OONI backends lookup call.
|
|
|
|
func (s *Session) MaybeLookupBackends() error {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
return s.MaybeLookupBackendsContext(context.Background())
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ErrAlreadyUsingProxy indicates that we cannot create a tunnel with
|
|
|
|
// a specific name because we already configured a proxy.
|
|
|
|
var ErrAlreadyUsingProxy = errors.New(
|
|
|
|
"session: cannot create a new tunnel of this kind: we are already using a proxy",
|
|
|
|
)
|
|
|
|
|
|
|
|
// MaybeStartTunnel starts the requested tunnel.
|
|
|
|
//
|
|
|
|
// This function silently succeeds if we're already using a tunnel with
|
|
|
|
// the same name or if the requested tunnel name is the empty string. This
|
|
|
|
// function fails, tho, when we already have a proxy or a tunnel with
|
|
|
|
// another name and we try to open a tunnel. This function of course also
|
|
|
|
// fails if we cannot start the requested tunnel. All in all, if you request
|
|
|
|
// for a tunnel name that is not the empty string and you get a nil error,
|
|
|
|
// you can be confident that session.ProxyURL() gives you the tunnel URL.
|
|
|
|
//
|
|
|
|
// The tunnel will be closed by session.Close().
|
|
|
|
func (s *Session) MaybeStartTunnel(ctx context.Context, name string) error {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// TODO(bassosimone): see if we can unify tunnelMu and mu.
|
2021-02-02 12:05:47 +01:00
|
|
|
s.tunnelMu.Lock()
|
|
|
|
defer s.tunnelMu.Unlock()
|
2021-04-04 11:23:03 +02:00
|
|
|
if name == "" {
|
|
|
|
// There is no point in continuing if we know
|
|
|
|
// we don't need to do anything.
|
|
|
|
return nil
|
|
|
|
}
|
2021-02-02 12:05:47 +01:00
|
|
|
if s.tunnel != nil && s.tunnelName == name {
|
|
|
|
// We've been asked more than once to start the same tunnel.
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if s.proxyURL != nil && name == "" {
|
|
|
|
// The user configured a proxy and here we're not actually trying
|
|
|
|
// to start any tunnel since `name` is empty.
|
2021-04-04 11:23:03 +02:00
|
|
|
// TODO(bassosimone): this if branch is probably useless now
|
|
|
|
// because we stop above when name is "".
|
2021-02-02 12:05:47 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if s.proxyURL != nil || s.tunnel != nil {
|
|
|
|
// We already have a proxy or we have a different tunnel. Because a tunnel
|
|
|
|
// sets a proxy, the second check for s.tunnel is for robustness.
|
|
|
|
return ErrAlreadyUsingProxy
|
|
|
|
}
|
2021-04-04 11:23:03 +02:00
|
|
|
s.logger.Infof("starting '%s' tunnel; please be patient...", name)
|
2021-04-03 20:12:56 +02:00
|
|
|
tunnel, err := tunnel.Start(ctx, &tunnel.Config{
|
2021-04-04 12:08:13 +02:00
|
|
|
Name: name,
|
2021-04-05 12:02:35 +02:00
|
|
|
Session: &sessionTunnelEarlySession{},
|
2021-04-04 12:08:13 +02:00
|
|
|
TorArgs: s.TorArgs(),
|
|
|
|
TorBinary: s.TorBinary(),
|
2021-04-05 11:27:41 +02:00
|
|
|
TunnelDir: s.tunnelDir,
|
2021-02-02 12:05:47 +01:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Implementation note: tunnel _may_ be NIL here if name is ""
|
|
|
|
if tunnel == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
s.tunnelName = name
|
|
|
|
s.tunnel = tunnel
|
|
|
|
s.proxyURL = tunnel.SOCKS5ProxyURL()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewExperimentBuilder returns a new experiment builder
|
|
|
|
// for the experiment with the given name, or an error if
|
|
|
|
// there's no such experiment with the given name
|
|
|
|
func (s *Session) NewExperimentBuilder(name string) (*ExperimentBuilder, error) {
|
|
|
|
return newExperimentBuilder(s, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewProbeServicesClient creates a new client for talking with the
|
|
|
|
// OONI probe services. This function will benchmark the available
|
|
|
|
// probe services, and select the fastest. In case all probe services
|
|
|
|
// seem to be down, we try again applying circumvention tactics.
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// This function will fail IMMEDIATELY if given a cancelled context.
|
2021-02-02 12:05:47 +01:00
|
|
|
func (s *Session) NewProbeServicesClient(ctx context.Context) (*probeservices.Client, error) {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
if ctx.Err() != nil {
|
|
|
|
return nil, ctx.Err() // helps with testing
|
|
|
|
}
|
|
|
|
if err := s.maybeLookupBackendsContext(ctx); err != nil {
|
2021-02-02 12:05:47 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
if err := s.maybeLookupLocationContext(ctx); err != nil {
|
2021-02-02 12:05:47 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if s.selectedProbeServiceHook != nil {
|
|
|
|
s.selectedProbeServiceHook(s.selectedProbeService)
|
|
|
|
}
|
|
|
|
return probeservices.NewClient(s, *s.selectedProbeService)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewSubmitter creates a new submitter instance.
|
|
|
|
func (s *Session) NewSubmitter(ctx context.Context) (Submitter, error) {
|
|
|
|
psc, err := s.NewProbeServicesClient(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return probeservices.NewSubmitter(psc, s.Logger()), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewOrchestraClient creates a new orchestra client. This client is registered
|
|
|
|
// and logged in with the OONI orchestra. An error is returned on failure.
|
2021-04-02 12:03:18 +02:00
|
|
|
//
|
|
|
|
// This function is DEPRECATED. New code SHOULD NOT use it. It will eventually
|
|
|
|
// be made private or entirely removed from the codebase.
|
|
|
|
func (s *Session) NewOrchestraClient(ctx context.Context) (*probeservices.Client, error) {
|
2021-02-02 12:05:47 +01:00
|
|
|
clnt, err := s.NewProbeServicesClient(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return s.initOrchestraClient(ctx, clnt, clnt.MaybeLogin)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Platform returns the current platform. The platform is one of:
|
|
|
|
//
|
|
|
|
// - android
|
|
|
|
// - ios
|
|
|
|
// - linux
|
|
|
|
// - macos
|
|
|
|
// - windows
|
|
|
|
// - unknown
|
|
|
|
//
|
|
|
|
// When running on the iOS simulator, the returned platform is
|
|
|
|
// macos rather than ios if CGO is disabled. This is a known issue,
|
|
|
|
// that however should have a very limited impact.
|
|
|
|
func (s *Session) Platform() string {
|
|
|
|
return platform.Name()
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProbeASNString returns the probe ASN as a string.
|
|
|
|
func (s *Session) ProbeASNString() string {
|
|
|
|
return fmt.Sprintf("AS%d", s.ProbeASN())
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProbeASN returns the probe ASN as an integer.
|
|
|
|
func (s *Session) ProbeASN() uint {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
asn := geolocate.DefaultProbeASN
|
|
|
|
if s.location != nil {
|
|
|
|
asn = s.location.ASN
|
|
|
|
}
|
|
|
|
return asn
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProbeCC returns the probe CC.
|
|
|
|
func (s *Session) ProbeCC() string {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
cc := geolocate.DefaultProbeCC
|
|
|
|
if s.location != nil {
|
|
|
|
cc = s.location.CountryCode
|
|
|
|
}
|
|
|
|
return cc
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProbeNetworkName returns the probe network name.
|
|
|
|
func (s *Session) ProbeNetworkName() string {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
nn := geolocate.DefaultProbeNetworkName
|
|
|
|
if s.location != nil {
|
|
|
|
nn = s.location.NetworkName
|
|
|
|
}
|
|
|
|
return nn
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProbeIP returns the probe IP.
|
|
|
|
func (s *Session) ProbeIP() string {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
ip := geolocate.DefaultProbeIP
|
|
|
|
if s.location != nil {
|
|
|
|
ip = s.location.ProbeIP
|
|
|
|
}
|
|
|
|
return ip
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProxyURL returns the Proxy URL, or nil if not set
|
|
|
|
func (s *Session) ProxyURL() *url.URL {
|
|
|
|
return s.proxyURL
|
|
|
|
}
|
|
|
|
|
|
|
|
// ResolverASNString returns the resolver ASN as a string
|
|
|
|
func (s *Session) ResolverASNString() string {
|
|
|
|
return fmt.Sprintf("AS%d", s.ResolverASN())
|
|
|
|
}
|
|
|
|
|
|
|
|
// ResolverASN returns the resolver ASN
|
|
|
|
func (s *Session) ResolverASN() uint {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
asn := geolocate.DefaultResolverASN
|
|
|
|
if s.location != nil {
|
|
|
|
asn = s.location.ResolverASN
|
|
|
|
}
|
|
|
|
return asn
|
|
|
|
}
|
|
|
|
|
|
|
|
// ResolverIP returns the resolver IP
|
|
|
|
func (s *Session) ResolverIP() string {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
ip := geolocate.DefaultResolverIP
|
|
|
|
if s.location != nil {
|
|
|
|
ip = s.location.ResolverIP
|
|
|
|
}
|
|
|
|
return ip
|
|
|
|
}
|
|
|
|
|
|
|
|
// ResolverNetworkName returns the resolver network name.
|
|
|
|
func (s *Session) ResolverNetworkName() string {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
nn := geolocate.DefaultResolverNetworkName
|
|
|
|
if s.location != nil {
|
|
|
|
nn = s.location.ResolverNetworkName
|
|
|
|
}
|
|
|
|
return nn
|
|
|
|
}
|
|
|
|
|
|
|
|
// SoftwareName returns the application name.
|
|
|
|
func (s *Session) SoftwareName() string {
|
|
|
|
return s.softwareName
|
|
|
|
}
|
|
|
|
|
|
|
|
// SoftwareVersion returns the application version.
|
|
|
|
func (s *Session) SoftwareVersion() string {
|
|
|
|
return s.softwareVersion
|
|
|
|
}
|
|
|
|
|
|
|
|
// TempDir returns the temporary directory.
|
|
|
|
func (s *Session) TempDir() string {
|
|
|
|
return s.tempDir
|
|
|
|
}
|
|
|
|
|
|
|
|
// TorArgs returns the configured extra args for the tor binary. If not set
|
|
|
|
// we will not pass in any extra arg. Applies to `-OTunnel=tor` mainly.
|
|
|
|
func (s *Session) TorArgs() []string {
|
|
|
|
return s.torArgs
|
|
|
|
}
|
|
|
|
|
|
|
|
// TorBinary returns the configured path to the tor binary. If not set
|
|
|
|
// we will attempt to use "tor". Applies to `-OTunnel=tor` mainly.
|
|
|
|
func (s *Session) TorBinary() string {
|
|
|
|
return s.torBinary
|
|
|
|
}
|
|
|
|
|
|
|
|
// UserAgent constructs the user agent to be used in this session.
|
|
|
|
func (s *Session) UserAgent() (useragent string) {
|
|
|
|
useragent += s.softwareName + "/" + s.softwareVersion
|
|
|
|
useragent += " ooniprobe-engine/" + version.Version
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// getAvailableProbeServicesUnlocked returns the available probe
|
|
|
|
// services. This function WILL NOT acquire the mu mutex, therefore,
|
|
|
|
// you MUST ensure you are using it from a locked context.
|
|
|
|
func (s *Session) getAvailableProbeServicesUnlocked() []model.Service {
|
2021-02-02 12:05:47 +01:00
|
|
|
if len(s.availableProbeServices) > 0 {
|
|
|
|
return s.availableProbeServices
|
|
|
|
}
|
|
|
|
return probeservices.Default()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Session) initOrchestraClient(
|
|
|
|
ctx context.Context, clnt *probeservices.Client,
|
|
|
|
maybeLogin func(ctx context.Context) error,
|
|
|
|
) (*probeservices.Client, error) {
|
|
|
|
// The original implementation has as its only use case that we
|
|
|
|
// were registering and logging in for sending an update regarding
|
|
|
|
// the probe whereabouts. Yet here in probe-engine, the orchestra
|
|
|
|
// is currently only used to fetch inputs. For this purpose, we don't
|
|
|
|
// need to communicate any specific information. The code that will
|
|
|
|
// perform an update used to be responsible of doing that. Now, we
|
|
|
|
// are not using orchestra for this purpose anymore.
|
|
|
|
meta := probeservices.Metadata{
|
|
|
|
Platform: "miniooni",
|
|
|
|
ProbeASN: "AS0",
|
|
|
|
ProbeCC: "ZZ",
|
|
|
|
SoftwareName: "miniooni",
|
|
|
|
SoftwareVersion: "0.1.0-dev",
|
|
|
|
SupportedTests: []string{"web_connectivity"},
|
|
|
|
}
|
|
|
|
if err := clnt.MaybeRegister(ctx, meta); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := maybeLogin(ctx); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return clnt, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ErrAllProbeServicesFailed indicates all probe services failed.
|
|
|
|
var ErrAllProbeServicesFailed = errors.New("all available probe services failed")
|
|
|
|
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// maybeLookupBackendsContext uses testMaybeLookupBackendsContext if
|
|
|
|
// not nil, otherwise it calls MaybeLookupBackendsContext.
|
|
|
|
func (s *Session) maybeLookupBackendsContext(ctx context.Context) error {
|
|
|
|
if s.testMaybeLookupBackendsContext != nil {
|
|
|
|
return s.testMaybeLookupBackendsContext(ctx)
|
|
|
|
}
|
|
|
|
return s.MaybeLookupBackendsContext(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaybeLookupBackendsContext is like MaybeLookupBackends but with context.
|
|
|
|
func (s *Session) MaybeLookupBackendsContext(ctx context.Context) error {
|
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
if s.selectedProbeService != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
s.queryProbeServicesCount.Add(1)
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
candidates := probeservices.TryAll(ctx, s, s.getAvailableProbeServicesUnlocked())
|
2021-02-02 12:05:47 +01:00
|
|
|
selected := probeservices.SelectBest(candidates)
|
|
|
|
if selected == nil {
|
|
|
|
return ErrAllProbeServicesFailed
|
|
|
|
}
|
|
|
|
s.logger.Infof("session: using probe services: %+v", selected.Endpoint)
|
|
|
|
s.selectedProbeService = &selected.Endpoint
|
|
|
|
s.availableTestHelpers = selected.TestHelpers
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// LookupLocationContext performs a location lookup. If you want memoisation
|
|
|
|
// of the results, you should use MaybeLookupLocationContext.
|
|
|
|
func (s *Session) LookupLocationContext(ctx context.Context) (*geolocate.Results, error) {
|
|
|
|
// Implementation note: we don't perform the lookup of the resolver IP
|
|
|
|
// when we are using a proxy because that might leak information.
|
|
|
|
task := geolocate.Must(geolocate.NewTask(geolocate.Config{
|
|
|
|
EnableResolverLookup: s.proxyURL == nil,
|
|
|
|
Logger: s.Logger(),
|
fix(geolocate): no proxy when discovering our IP address (#251)
* fix(geolocate): no proxy when discovering our IP address
The use case of --proxy is that you cannot contact the OONI
backend otherwise. It is wrong, though, using the proxy when
discovering our IP address. The measurement won't use the
proxy anyway. Therefore, we need to use the IP address that
is performing the measurement. Not the one of the proxy.
What's more, stun is not using a proxy. Therefore, it does
not make much sense that http IP resolvers use a proxy. This
leads to inconsistencies. So, here's anothe reason why this
patch is a good thing (TM).
Finally, because knowing the IP address enables us to sanitize
the data, it's important we discover the correct IP.
Now, up until this point, the `--proxy` option has mostly
been a developers toy. But, users have asked us to have the
possibility of configuring a proxy.
This explains why I have been looking into making `--proxy`
right for a couple of hours now.
See https://github.com/ooni/probe/issues/1382
* fix(session): properly configure the IP lookupper
2021-03-10 12:01:08 +01:00
|
|
|
Resolver: s.resolver,
|
2021-02-02 12:05:47 +01:00
|
|
|
UserAgent: s.UserAgent(),
|
|
|
|
}))
|
|
|
|
return task.Run(ctx)
|
|
|
|
}
|
|
|
|
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// lookupLocationContext calls testLookupLocationContext if set and
|
|
|
|
// otherwise calls LookupLocationContext.
|
|
|
|
func (s *Session) lookupLocationContext(ctx context.Context) (*geolocate.Results, error) {
|
|
|
|
if s.testLookupLocationContext != nil {
|
|
|
|
return s.testLookupLocationContext(ctx)
|
|
|
|
}
|
|
|
|
return s.LookupLocationContext(ctx)
|
|
|
|
}
|
|
|
|
|
2021-02-02 12:05:47 +01:00
|
|
|
// MaybeLookupLocationContext is like MaybeLookupLocation but with a context
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
// that can be used to interrupt this long running operation. This function
|
|
|
|
// will fail IMMEDIATELY if given a cancelled context.
|
2021-02-02 12:05:47 +01:00
|
|
|
func (s *Session) MaybeLookupLocationContext(ctx context.Context) error {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
if ctx.Err() != nil {
|
|
|
|
return ctx.Err() // helps with testing
|
|
|
|
}
|
|
|
|
defer s.mu.Unlock()
|
|
|
|
s.mu.Lock()
|
2021-02-02 12:05:47 +01:00
|
|
|
if s.location == nil {
|
feat(session): expose CheckIn method (#266)
* feat(session): expose CheckIn method
It seems to me the right thing to do is to query the CheckIn API
from the Session rather than querying it from InputLoader.
Then, InputLoader could just take a reference to a Session-like
interface that allows this functionality.
So, this diff exposes the Session.CheckIn method.
Doing that, in turn, required some refactoring to allow for
more and better unit tests.
While doing that, I also noticed that Session required a mutex
to be a well-behaving type, so I did that.
While doing that, I also tried to cover all the lines in session.go
and, as part of that, I have removed unused code.
Reference issue: https://github.com/ooni/probe/issues/1299.
* fix: reinstate comment I shan't have removed
* fix: repair broken test
* fix: a bit more coverage, annotations, etc.
* Update internal/engine/session.go
* Update internal/engine/session_integration_test.go
* Update internal/engine/session_internal_test.go
2021-03-29 15:04:41 +02:00
|
|
|
location, err := s.lookupLocationContext(ctx)
|
2021-02-02 12:05:47 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
s.location = location
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ model.ExperimentSession = &Session{}
|