2021-02-02 12:05:47 +01:00
|
|
|
package engine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
|
refactor: flatten and separate (#353)
* refactor(atomicx): move outside the engine package
After merging probe-engine into probe-cli, my impression is that we have
too much unnecessary nesting of packages in this repository.
The idea of this commit and of a bunch of following commits will instead
be to reduce the nesting and simplify the structure.
While there, improve the documentation.
* fix: always use the atomicx package
For consistency, never use sync/atomic and always use ./internal/atomicx
so we can just grep and make sure we're not risking to crash if we make
a subtle mistake on a 32 bit platform.
While there, mention in the contributing guidelines that we want to
always prefer the ./internal/atomicx package over sync/atomic.
* fix(atomicx): remove unnecessary constructor
We don't need a constructor here. The default constructed `&Int64{}`
instance is already usable and the constructor does not add anything to
what we are doing, rather it just creates extra confusion.
* cleanup(atomicx): we are not using Float64
Because atomicx.Float64 is unused, we can safely zap it.
* cleanup(atomicx): simplify impl and improve tests
We can simplify the implementation by using defer and by letting
the Load() method call Add(0).
We can improve tests by making many goroutines updated the
atomic int64 value concurrently.
* refactor(fsx): can live in the ./internal pkg
Let us reduce the amount of nesting. While there, ensure that the
package only exports the bare minimum, and improve the documentation
of the tests, to ease reading the code.
* refactor: move runtimex to ./internal
* refactor: move shellx into the ./internal package
While there, remove unnecessary dependency between packages.
While there, specify in the contributing guidelines that
one should use x/sys/execabs instead of os/exec.
* refactor: move ooapi into the ./internal pkg
* refactor(humanize): move to ./internal and better docs
* refactor: move platform to ./internal
* refactor(randx): move to ./internal
* refactor(multierror): move into the ./internal pkg
* refactor(kvstore): all kvstores in ./internal
Rather than having part of the kvstore inside ./internal/engine/kvstore
and part in ./internal/engine/kvstore.go, let us put every piece of code
that is kvstore related into the ./internal/kvstore package.
* fix(kvstore): always return ErrNoSuchKey on Get() error
It should help to use the kvstore everywhere removing all the
copies that are lingering around the tree.
* sessionresolver: make KVStore mandatory
Simplifies implementation. While there, use the ./internal/kvstore
package rather than having our private implementation.
* fix(ooapi): use the ./internal/kvstore package
* fix(platform): better documentation
2021-06-04 10:34:18 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
2021-06-22 13:00:29 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
2021-02-02 12:05:47 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/geolocate"
|
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/probeservices"
|
2022-09-02 14:44:23 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/engine/sessionresolver"
|
refactor: flatten and separate (#353)
* refactor(atomicx): move outside the engine package
After merging probe-engine into probe-cli, my impression is that we have
too much unnecessary nesting of packages in this repository.
The idea of this commit and of a bunch of following commits will instead
be to reduce the nesting and simplify the structure.
While there, improve the documentation.
* fix: always use the atomicx package
For consistency, never use sync/atomic and always use ./internal/atomicx
so we can just grep and make sure we're not risking to crash if we make
a subtle mistake on a 32 bit platform.
While there, mention in the contributing guidelines that we want to
always prefer the ./internal/atomicx package over sync/atomic.
* fix(atomicx): remove unnecessary constructor
We don't need a constructor here. The default constructed `&Int64{}`
instance is already usable and the constructor does not add anything to
what we are doing, rather it just creates extra confusion.
* cleanup(atomicx): we are not using Float64
Because atomicx.Float64 is unused, we can safely zap it.
* cleanup(atomicx): simplify impl and improve tests
We can simplify the implementation by using defer and by letting
the Load() method call Add(0).
We can improve tests by making many goroutines updated the
atomic int64 value concurrently.
* refactor(fsx): can live in the ./internal pkg
Let us reduce the amount of nesting. While there, ensure that the
package only exports the bare minimum, and improve the documentation
of the tests, to ease reading the code.
* refactor: move runtimex to ./internal
* refactor: move shellx into the ./internal package
While there, remove unnecessary dependency between packages.
While there, specify in the contributing guidelines that
one should use x/sys/execabs instead of os/exec.
* refactor: move ooapi into the ./internal pkg
* refactor(humanize): move to ./internal and better docs
* refactor: move platform to ./internal
* refactor(randx): move to ./internal
* refactor(multierror): move into the ./internal pkg
* refactor(kvstore): all kvstores in ./internal
Rather than having part of the kvstore inside ./internal/engine/kvstore
and part in ./internal/engine/kvstore.go, let us put every piece of code
that is kvstore related into the ./internal/kvstore package.
* fix(kvstore): always return ErrNoSuchKey on Get() error
It should help to use the kvstore everywhere removing all the
copies that are lingering around the tree.
* sessionresolver: make KVStore mandatory
Simplifies implementation. While there, use the ./internal/kvstore
package rather than having our private implementation.
* fix(ooapi): use the ./internal/kvstore package
* fix(platform): better documentation
2021-06-04 10:34:18 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/kvstore"
|
2022-01-03 13:53:23 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
2022-05-30 22:00:45 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
refactor: flatten and separate (#353)
* refactor(atomicx): move outside the engine package
After merging probe-engine into probe-cli, my impression is that we have
too much unnecessary nesting of packages in this repository.
The idea of this commit and of a bunch of following commits will instead
be to reduce the nesting and simplify the structure.
While there, improve the documentation.
* fix: always use the atomicx package
For consistency, never use sync/atomic and always use ./internal/atomicx
so we can just grep and make sure we're not risking to crash if we make
a subtle mistake on a 32 bit platform.
While there, mention in the contributing guidelines that we want to
always prefer the ./internal/atomicx package over sync/atomic.
* fix(atomicx): remove unnecessary constructor
We don't need a constructor here. The default constructed `&Int64{}`
instance is already usable and the constructor does not add anything to
what we are doing, rather it just creates extra confusion.
* cleanup(atomicx): we are not using Float64
Because atomicx.Float64 is unused, we can safely zap it.
* cleanup(atomicx): simplify impl and improve tests
We can simplify the implementation by using defer and by letting
the Load() method call Add(0).
We can improve tests by making many goroutines updated the
atomic int64 value concurrently.
* refactor(fsx): can live in the ./internal pkg
Let us reduce the amount of nesting. While there, ensure that the
package only exports the bare minimum, and improve the documentation
of the tests, to ease reading the code.
* refactor: move runtimex to ./internal
* refactor: move shellx into the ./internal package
While there, remove unnecessary dependency between packages.
While there, specify in the contributing guidelines that
one should use x/sys/execabs instead of os/exec.
* refactor: move ooapi into the ./internal pkg
* refactor(humanize): move to ./internal and better docs
* refactor: move platform to ./internal
* refactor(randx): move to ./internal
* refactor(multierror): move into the ./internal pkg
* refactor(kvstore): all kvstores in ./internal
Rather than having part of the kvstore inside ./internal/engine/kvstore
and part in ./internal/engine/kvstore.go, let us put every piece of code
that is kvstore related into the ./internal/kvstore package.
* fix(kvstore): always return ErrNoSuchKey on Get() error
It should help to use the kvstore everywhere removing all the
copies that are lingering around the tree.
* sessionresolver: make KVStore mandatory
Simplifies implementation. While there, use the ./internal/kvstore
package rather than having our private implementation.
* fix(ooapi): use the ./internal/kvstore package
* fix(platform): better documentation
2021-06-04 10:34:18 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/platform"
|
2021-06-04 15:15:41 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/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 {
|
2022-01-03 13:53:23 +01:00
|
|
|
AvailableProbeServices []model.OOAPIService
|
|
|
|
KVStore model.KeyValueStore
|
2021-02-02 12:05:47 +01:00
|
|
|
Logger model.Logger
|
|
|
|
ProxyURL *url.URL
|
|
|
|
SoftwareName string
|
|
|
|
SoftwareVersion string
|
|
|
|
TempDir string
|
|
|
|
TorArgs []string
|
|
|
|
TorBinary string
|
2021-04-05 11:27:41 +02:00
|
|
|
|
2022-10-03 16:52:20 +02:00
|
|
|
// SnowflakeRendezvous is the rendezvous method
|
|
|
|
// to be used by the torsf tunnel
|
|
|
|
SnowflakeRendezvous 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 {
|
2022-01-03 13:53:23 +01:00
|
|
|
availableProbeServices []model.OOAPIService
|
|
|
|
availableTestHelpers map[string][]model.OOAPIService
|
2021-02-02 12:05:47 +01:00
|
|
|
byteCounter *bytecounter.Counter
|
2022-01-07 18:33:37 +01:00
|
|
|
httpDefaultTransport model.HTTPTransport
|
2022-01-03 13:53:23 +01:00
|
|
|
kvStore model.KeyValueStore
|
2021-02-02 12:05:47 +01:00
|
|
|
location *geolocate.Results
|
|
|
|
logger model.Logger
|
|
|
|
proxyURL *url.URL
|
|
|
|
queryProbeServicesCount *atomicx.Int64
|
|
|
|
resolver *sessionresolver.Resolver
|
2022-01-03 13:53:23 +01:00
|
|
|
selectedProbeServiceHook func(*model.OOAPIService)
|
|
|
|
selectedProbeService *model.OOAPIService
|
2021-02-02 12:05:47 +01:00
|
|
|
softwareName string
|
|
|
|
softwareVersion string
|
|
|
|
tempDir 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
|
|
|
|
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)
|
2021-04-05 15:28:13 +02:00
|
|
|
|
|
|
|
// torArgs contains the optional arguments for tor that we may need
|
|
|
|
// to pass to urlgetter when it uses a tor tunnel.
|
|
|
|
torArgs []string
|
|
|
|
|
|
|
|
// torBinary contains the optional path to the tor binary that we
|
|
|
|
// may need to pass to urlgetter when it uses a tor tunnel.
|
|
|
|
torBinary string
|
|
|
|
|
feat(torsf): collect tor logs, select rendezvous method, count bytes (#683)
This diff contains significant improvements over the previous
implementation of the torsf experiment.
We add support for configuring different rendezvous methods after
the convo at https://github.com/ooni/probe/issues/2004. In doing
that, I've tried to use a terminology that is consistent with the
names being actually used by tor developers.
In terms of what to do next, this diff basically instruments
torsf to always rendezvous using domain fronting. Yet, it's also
possible to change the rendezvous method from the command line,
when using miniooni, which allows to experiment a bit more. In the
same vein, by default we use a persistent tor datadir, but it's
also possible to use a temporary datadir using the cmdline.
Here's how a generic invocation of `torsf` looks like:
```bash
./miniooni -O DisablePersistentDatadir=true \
-O RendezvousMethod=amp \
-O DisableProgress=true \
torsf
```
(The default is `DisablePersistentDatadir=false` and
`RendezvousMethod=domain_fronting`.)
With this implementation, we can start measuring whether snowflake
and tor together can boostrap, which seems the most important thing
to focus on at the beginning. Understanding why the bootstrap most
often does not converge with a temporary datadir on Android devices
remains instead an open problem for now. (I'll also update the
relevant issues or create new issues after commit this.)
We also address some methodology improvements that were proposed
in https://github.com/ooni/probe/issues/1686. Namely:
1. we record the tor version;
2. we include the bootstrap percentage by reading the logs;
3. we set the anomaly key correctly;
4. we measure the bytes send and received (by `tor` not by `snowflake`, since
doing it for snowflake seems more complex at this stage).
What remains to be done is the possibility of including Snowflake
events into the measurement, which is not possible until the new
improvements at common/event in snowflake.git are included into a
tagged version of snowflake itself. (I'll make sure to mention
this aspect to @cohosh in https://github.com/ooni/probe/issues/2004.)
2022-02-07 17:05:36 +01:00
|
|
|
// tunnelDir is the directory used by tunnels.
|
|
|
|
tunnelDir string
|
|
|
|
|
2021-04-05 15:28:13 +02:00
|
|
|
// tunnel is the optional tunnel that we may be using. It is created
|
|
|
|
// by NewSession and it is cleaned up by Close.
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
// sessionProbeServicesClientForCheckIn returns the probe services
|
|
|
|
// client that we should be using for performing the check-in.
|
|
|
|
type sessionProbeServicesClientForCheckIn interface {
|
2022-01-03 13:53:23 +01:00
|
|
|
CheckIn(ctx context.Context, config model.OOAPICheckInConfig) (*model.OOAPICheckInInfo, error)
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
2021-04-05 15:28:13 +02:00
|
|
|
// NewSession creates a new session. This factory function will
|
|
|
|
// execute the following steps:
|
|
|
|
//
|
|
|
|
// 1. Make sure the config is sane, apply reasonable defaults
|
|
|
|
// where possible, otherwise return an error.
|
|
|
|
//
|
|
|
|
// 2. Create a temporary directory.
|
|
|
|
//
|
|
|
|
// 3. Create an instance of the session.
|
|
|
|
//
|
|
|
|
// 4. If the user requested for a proxy that entails a tunnel (at the
|
|
|
|
// moment of writing this note, either psiphon or tor), then start the
|
|
|
|
// requested tunnel and configure it as our proxy.
|
|
|
|
//
|
|
|
|
// 5. Create a compound resolver for the session that will attempt
|
|
|
|
// to use a bunch of DoT/DoH servers before falling back to the system
|
|
|
|
// resolver if nothing else works (see the sessionresolver pkg). This
|
|
|
|
// sessionresolver will be using the configured proxy, if any.
|
|
|
|
//
|
|
|
|
// 6. Create the default HTTP transport that we should be using when
|
|
|
|
// we communicate with the OONI backends. This transport will be
|
|
|
|
// using the configured proxy, if any.
|
|
|
|
//
|
|
|
|
// If any of these steps fails, then we cannot create a measurement
|
|
|
|
// session and we return an error.
|
|
|
|
func NewSession(ctx context.Context, config SessionConfig) (*Session, error) {
|
2021-02-02 12:05:47 +01:00
|
|
|
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 {
|
refactor: flatten and separate (#353)
* refactor(atomicx): move outside the engine package
After merging probe-engine into probe-cli, my impression is that we have
too much unnecessary nesting of packages in this repository.
The idea of this commit and of a bunch of following commits will instead
be to reduce the nesting and simplify the structure.
While there, improve the documentation.
* fix: always use the atomicx package
For consistency, never use sync/atomic and always use ./internal/atomicx
so we can just grep and make sure we're not risking to crash if we make
a subtle mistake on a 32 bit platform.
While there, mention in the contributing guidelines that we want to
always prefer the ./internal/atomicx package over sync/atomic.
* fix(atomicx): remove unnecessary constructor
We don't need a constructor here. The default constructed `&Int64{}`
instance is already usable and the constructor does not add anything to
what we are doing, rather it just creates extra confusion.
* cleanup(atomicx): we are not using Float64
Because atomicx.Float64 is unused, we can safely zap it.
* cleanup(atomicx): simplify impl and improve tests
We can simplify the implementation by using defer and by letting
the Load() method call Add(0).
We can improve tests by making many goroutines updated the
atomic int64 value concurrently.
* refactor(fsx): can live in the ./internal pkg
Let us reduce the amount of nesting. While there, ensure that the
package only exports the bare minimum, and improve the documentation
of the tests, to ease reading the code.
* refactor: move runtimex to ./internal
* refactor: move shellx into the ./internal package
While there, remove unnecessary dependency between packages.
While there, specify in the contributing guidelines that
one should use x/sys/execabs instead of os/exec.
* refactor: move ooapi into the ./internal pkg
* refactor(humanize): move to ./internal and better docs
* refactor: move platform to ./internal
* refactor(randx): move to ./internal
* refactor(multierror): move into the ./internal pkg
* refactor(kvstore): all kvstores in ./internal
Rather than having part of the kvstore inside ./internal/engine/kvstore
and part in ./internal/engine/kvstore.go, let us put every piece of code
that is kvstore related into the ./internal/kvstore package.
* fix(kvstore): always return ErrNoSuchKey on Get() error
It should help to use the kvstore everywhere removing all the
copies that are lingering around the tree.
* sessionresolver: make KVStore mandatory
Simplifies implementation. While there, use the ./internal/kvstore
package rather than having our private implementation.
* fix(ooapi): use the ./internal/kvstore package
* fix(platform): better documentation
2021-06-04 10:34:18 +02:00
|
|
|
config.KVStore = &kvstore.Memory{}
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
// 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,
|
refactor: flatten and separate (#353)
* refactor(atomicx): move outside the engine package
After merging probe-engine into probe-cli, my impression is that we have
too much unnecessary nesting of packages in this repository.
The idea of this commit and of a bunch of following commits will instead
be to reduce the nesting and simplify the structure.
While there, improve the documentation.
* fix: always use the atomicx package
For consistency, never use sync/atomic and always use ./internal/atomicx
so we can just grep and make sure we're not risking to crash if we make
a subtle mistake on a 32 bit platform.
While there, mention in the contributing guidelines that we want to
always prefer the ./internal/atomicx package over sync/atomic.
* fix(atomicx): remove unnecessary constructor
We don't need a constructor here. The default constructed `&Int64{}`
instance is already usable and the constructor does not add anything to
what we are doing, rather it just creates extra confusion.
* cleanup(atomicx): we are not using Float64
Because atomicx.Float64 is unused, we can safely zap it.
* cleanup(atomicx): simplify impl and improve tests
We can simplify the implementation by using defer and by letting
the Load() method call Add(0).
We can improve tests by making many goroutines updated the
atomic int64 value concurrently.
* refactor(fsx): can live in the ./internal pkg
Let us reduce the amount of nesting. While there, ensure that the
package only exports the bare minimum, and improve the documentation
of the tests, to ease reading the code.
* refactor: move runtimex to ./internal
* refactor: move shellx into the ./internal package
While there, remove unnecessary dependency between packages.
While there, specify in the contributing guidelines that
one should use x/sys/execabs instead of os/exec.
* refactor: move ooapi into the ./internal pkg
* refactor(humanize): move to ./internal and better docs
* refactor: move platform to ./internal
* refactor(randx): move to ./internal
* refactor(multierror): move into the ./internal pkg
* refactor(kvstore): all kvstores in ./internal
Rather than having part of the kvstore inside ./internal/engine/kvstore
and part in ./internal/engine/kvstore.go, let us put every piece of code
that is kvstore related into the ./internal/kvstore package.
* fix(kvstore): always return ErrNoSuchKey on Get() error
It should help to use the kvstore everywhere removing all the
copies that are lingering around the tree.
* sessionresolver: make KVStore mandatory
Simplifies implementation. While there, use the ./internal/kvstore
package rather than having our private implementation.
* fix(ooapi): use the ./internal/kvstore package
* fix(platform): better documentation
2021-06-04 10:34:18 +02:00
|
|
|
queryProbeServicesCount: &atomicx.Int64{},
|
2021-02-02 12:05:47 +01:00
|
|
|
softwareName: config.SoftwareName,
|
|
|
|
softwareVersion: config.SoftwareVersion,
|
|
|
|
tempDir: tempDir,
|
|
|
|
torArgs: config.TorArgs,
|
|
|
|
torBinary: config.TorBinary,
|
feat(torsf): collect tor logs, select rendezvous method, count bytes (#683)
This diff contains significant improvements over the previous
implementation of the torsf experiment.
We add support for configuring different rendezvous methods after
the convo at https://github.com/ooni/probe/issues/2004. In doing
that, I've tried to use a terminology that is consistent with the
names being actually used by tor developers.
In terms of what to do next, this diff basically instruments
torsf to always rendezvous using domain fronting. Yet, it's also
possible to change the rendezvous method from the command line,
when using miniooni, which allows to experiment a bit more. In the
same vein, by default we use a persistent tor datadir, but it's
also possible to use a temporary datadir using the cmdline.
Here's how a generic invocation of `torsf` looks like:
```bash
./miniooni -O DisablePersistentDatadir=true \
-O RendezvousMethod=amp \
-O DisableProgress=true \
torsf
```
(The default is `DisablePersistentDatadir=false` and
`RendezvousMethod=domain_fronting`.)
With this implementation, we can start measuring whether snowflake
and tor together can boostrap, which seems the most important thing
to focus on at the beginning. Understanding why the bootstrap most
often does not converge with a temporary datadir on Android devices
remains instead an open problem for now. (I'll also update the
relevant issues or create new issues after commit this.)
We also address some methodology improvements that were proposed
in https://github.com/ooni/probe/issues/1686. Namely:
1. we record the tor version;
2. we include the bootstrap percentage by reading the logs;
3. we set the anomaly key correctly;
4. we measure the bytes send and received (by `tor` not by `snowflake`, since
doing it for snowflake seems more complex at this stage).
What remains to be done is the possibility of including Snowflake
events into the measurement, which is not possible until the new
improvements at common/event in snowflake.git are included into a
tagged version of snowflake itself. (I'll make sure to mention
this aspect to @cohosh in https://github.com/ooni/probe/issues/2004.)
2022-02-07 17:05:36 +01:00
|
|
|
tunnelDir: config.TunnelDir,
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
2021-04-05 15:28:13 +02:00
|
|
|
proxyURL := config.ProxyURL
|
|
|
|
if proxyURL != nil {
|
|
|
|
switch proxyURL.Scheme {
|
2022-10-03 16:52:20 +02:00
|
|
|
case "psiphon", "tor", "torsf", "fake":
|
2021-04-05 19:18:00 +02:00
|
|
|
config.Logger.Infof(
|
|
|
|
"starting '%s' tunnel; please be patient...", proxyURL.Scheme)
|
feat(torsf): collect tor logs, select rendezvous method, count bytes (#683)
This diff contains significant improvements over the previous
implementation of the torsf experiment.
We add support for configuring different rendezvous methods after
the convo at https://github.com/ooni/probe/issues/2004. In doing
that, I've tried to use a terminology that is consistent with the
names being actually used by tor developers.
In terms of what to do next, this diff basically instruments
torsf to always rendezvous using domain fronting. Yet, it's also
possible to change the rendezvous method from the command line,
when using miniooni, which allows to experiment a bit more. In the
same vein, by default we use a persistent tor datadir, but it's
also possible to use a temporary datadir using the cmdline.
Here's how a generic invocation of `torsf` looks like:
```bash
./miniooni -O DisablePersistentDatadir=true \
-O RendezvousMethod=amp \
-O DisableProgress=true \
torsf
```
(The default is `DisablePersistentDatadir=false` and
`RendezvousMethod=domain_fronting`.)
With this implementation, we can start measuring whether snowflake
and tor together can boostrap, which seems the most important thing
to focus on at the beginning. Understanding why the bootstrap most
often does not converge with a temporary datadir on Android devices
remains instead an open problem for now. (I'll also update the
relevant issues or create new issues after commit this.)
We also address some methodology improvements that were proposed
in https://github.com/ooni/probe/issues/1686. Namely:
1. we record the tor version;
2. we include the bootstrap percentage by reading the logs;
3. we set the anomaly key correctly;
4. we measure the bytes send and received (by `tor` not by `snowflake`, since
doing it for snowflake seems more complex at this stage).
What remains to be done is the possibility of including Snowflake
events into the measurement, which is not possible until the new
improvements at common/event in snowflake.git are included into a
tagged version of snowflake itself. (I'll make sure to mention
this aspect to @cohosh in https://github.com/ooni/probe/issues/2004.)
2022-02-07 17:05:36 +01:00
|
|
|
tunnel, _, err := tunnel.Start(ctx, &tunnel.Config{
|
2022-10-03 16:52:20 +02:00
|
|
|
Logger: config.Logger,
|
|
|
|
Name: proxyURL.Scheme,
|
|
|
|
SnowflakeRendezvous: config.SnowflakeRendezvous,
|
|
|
|
Session: &sessionTunnelEarlySession{},
|
|
|
|
TorArgs: config.TorArgs,
|
|
|
|
TorBinary: config.TorBinary,
|
|
|
|
TunnelDir: config.TunnelDir,
|
2021-04-05 15:28:13 +02:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-04-05 19:18:00 +02:00
|
|
|
config.Logger.Infof("tunnel '%s' running...", proxyURL.Scheme)
|
2021-04-05 15:28:13 +02:00
|
|
|
sess.tunnel = tunnel
|
|
|
|
proxyURL = tunnel.SOCKS5ProxyURL()
|
2022-10-08 13:14:11 +02:00
|
|
|
case "none":
|
|
|
|
proxyURL = nil // explicit way of saying we don't want to use a tunnel
|
2021-04-05 15:28:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
sess.proxyURL = proxyURL
|
2021-03-03 11:28:39 +01:00
|
|
|
sess.resolver = &sessionresolver.Resolver{
|
|
|
|
ByteCounter: sess.byteCounter,
|
|
|
|
KVStore: config.KVStore,
|
|
|
|
Logger: sess.logger,
|
2021-04-05 15:28:13 +02:00
|
|
|
ProxyURL: proxyURL,
|
2021-03-03 11:28:39 +01:00
|
|
|
}
|
2022-06-09 00:30:18 +02:00
|
|
|
txp := netxlite.NewHTTPTransportWithLoggerResolverAndOptionalProxyURL(
|
|
|
|
sess.logger, sess.resolver, sess.proxyURL,
|
|
|
|
)
|
2022-06-05 21:22:27 +02:00
|
|
|
txp = bytecounter.WrapHTTPTransport(txp, sess.byteCounter)
|
2022-05-30 22:00:45 +02:00
|
|
|
sess.httpDefaultTransport = txp
|
2021-02-02 12:05:47 +01:00
|
|
|
return sess, nil
|
|
|
|
}
|
|
|
|
|
feat(torsf): collect tor logs, select rendezvous method, count bytes (#683)
This diff contains significant improvements over the previous
implementation of the torsf experiment.
We add support for configuring different rendezvous methods after
the convo at https://github.com/ooni/probe/issues/2004. In doing
that, I've tried to use a terminology that is consistent with the
names being actually used by tor developers.
In terms of what to do next, this diff basically instruments
torsf to always rendezvous using domain fronting. Yet, it's also
possible to change the rendezvous method from the command line,
when using miniooni, which allows to experiment a bit more. In the
same vein, by default we use a persistent tor datadir, but it's
also possible to use a temporary datadir using the cmdline.
Here's how a generic invocation of `torsf` looks like:
```bash
./miniooni -O DisablePersistentDatadir=true \
-O RendezvousMethod=amp \
-O DisableProgress=true \
torsf
```
(The default is `DisablePersistentDatadir=false` and
`RendezvousMethod=domain_fronting`.)
With this implementation, we can start measuring whether snowflake
and tor together can boostrap, which seems the most important thing
to focus on at the beginning. Understanding why the bootstrap most
often does not converge with a temporary datadir on Android devices
remains instead an open problem for now. (I'll also update the
relevant issues or create new issues after commit this.)
We also address some methodology improvements that were proposed
in https://github.com/ooni/probe/issues/1686. Namely:
1. we record the tor version;
2. we include the bootstrap percentage by reading the logs;
3. we set the anomaly key correctly;
4. we measure the bytes send and received (by `tor` not by `snowflake`, since
doing it for snowflake seems more complex at this stage).
What remains to be done is the possibility of including Snowflake
events into the measurement, which is not possible until the new
improvements at common/event in snowflake.git are included into a
tagged version of snowflake itself. (I'll make sure to mention
this aspect to @cohosh in https://github.com/ooni/probe/issues/2004.)
2022-02-07 17:05:36 +01:00
|
|
|
// TunnelDir returns the persistent directory used by tunnels.
|
|
|
|
func (s *Session) TunnelDir() string {
|
|
|
|
return s.tunnelDir
|
|
|
|
}
|
|
|
|
|
2021-02-02 12:05:47 +01:00
|
|
|
// 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();
|
|
|
|
//
|
2022-04-29 13:41:09 +02:00
|
|
|
// - RunType: if empty, set to model.RunTypeTimed;
|
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
|
|
|
//
|
|
|
|
// - 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(
|
2022-01-03 13:53:23 +01:00
|
|
|
ctx context.Context, config *model.OOAPICheckInConfig) (*model.OOAPICheckInInfo, 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 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 == "" {
|
2022-04-29 13:41:09 +02:00
|
|
|
config.RunType = model.RunTypeTimed // most conservative choice
|
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 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.
|
2022-01-03 13:53:23 +01:00
|
|
|
func (s *Session) GetTestHelpersByName(name string) ([]model.OOAPIService, 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.
|
2022-07-08 11:08:10 +02:00
|
|
|
func (s *Session) DefaultHTTPClient() model.HTTPClient {
|
2021-02-02 12:05:47 +01:00
|
|
|
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(
|
2022-01-03 13:53:23 +01:00
|
|
|
ctx context.Context, cc string) (map[string]model.OOAPITorTarget, error) {
|
2021-04-02 12:03:18 +02:00
|
|
|
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(
|
2022-01-03 13:53:23 +01:00
|
|
|
ctx context.Context, config model.OOAPIURLListConfig) ([]model.OOAPIURLInfo, error) {
|
2021-04-02 12:03:18 +02:00
|
|
|
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",
|
|
|
|
)
|
|
|
|
|
|
|
|
// 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
|
2022-08-17 10:57:03 +02:00
|
|
|
func (s *Session) NewExperimentBuilder(name string) (model.ExperimentBuilder, error) {
|
2022-07-08 13:12:12 +02:00
|
|
|
eb, err := newExperimentBuilder(s, name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return eb, nil
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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()
|
2022-08-28 20:00:25 +02:00
|
|
|
asn := model.DefaultProbeASN
|
2021-02-02 12:05:47 +01:00
|
|
|
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()
|
2022-08-28 20:00:25 +02:00
|
|
|
cc := model.DefaultProbeCC
|
2021-02-02 12:05:47 +01:00
|
|
|
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()
|
2022-08-28 20:00:25 +02:00
|
|
|
nn := model.DefaultProbeNetworkName
|
2021-02-02 12:05:47 +01:00
|
|
|
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()
|
2022-08-28 20:00:25 +02:00
|
|
|
ip := model.DefaultProbeIP
|
2021-02-02 12:05:47 +01:00
|
|
|
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()
|
2022-08-28 20:00:25 +02:00
|
|
|
asn := model.DefaultResolverASN
|
2021-02-02 12:05:47 +01:00
|
|
|
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()
|
2022-08-28 20:00:25 +02:00
|
|
|
ip := model.DefaultResolverIP
|
2021-02-02 12:05:47 +01:00
|
|
|
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()
|
2022-08-28 20:00:25 +02:00
|
|
|
nn := model.DefaultResolverNetworkName
|
2021-02-02 12:05:47 +01:00
|
|
|
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.
|
2022-01-03 13:53:23 +01:00
|
|
|
func (s *Session) getAvailableProbeServicesUnlocked() []model.OOAPIService {
|
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) {
|
2021-06-04 16:06:24 +02:00
|
|
|
task := geolocate.NewTask(geolocate.Config{
|
2021-04-07 18:48:02 +02:00
|
|
|
Logger: s.Logger(),
|
|
|
|
Resolver: s.resolver,
|
|
|
|
UserAgent: s.UserAgent(),
|
2021-06-04 16:06:24 +02:00
|
|
|
})
|
2021-02-02 12:05:47 +01:00
|
|
|
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{}
|