Store results/errors from individual ip/port combos (runs)
This commit is contained in:
parent
25ebafa427
commit
fad69bdef1
|
@ -89,13 +89,22 @@ func config(input model.MeasurementTarget) (*Config, error) {
|
|||
|
||||
// TestKeys contains the experiment results
|
||||
type TestKeys struct {
|
||||
Queries []*model.ArchivalDNSLookupResult `json:"queries"`
|
||||
TCPConnect []*model.ArchivalTCPConnectResult `json:"tcp_connect"`
|
||||
TLSHandshakes []*model.ArchivalTLSOrQUICHandshakeResult `json:"tls_handshakes"`
|
||||
SMTPErrors map[string][]*string `json:"smtp"`
|
||||
NoOpCounter uint8 `json:"successful_noops"`
|
||||
Queries []*model.ArchivalDNSLookupResult `json:"queries"`
|
||||
Runs map[string]IndividualTestKeys `json:"runs"`
|
||||
// Used for global failure (DNS resolution)
|
||||
Failure string `json:"failure"`
|
||||
// Used to indicate global failure state
|
||||
Failed bool `json:"failed"`
|
||||
}
|
||||
|
||||
// IndividualTestKeys contains results for TCP/IP level stuff for each address found
|
||||
// in the DNS lookup
|
||||
type IndividualTestKeys struct {
|
||||
NoOpCounter uint8
|
||||
TCPConnect []*model.ArchivalTCPConnectResult `json:"tcp_connect"`
|
||||
TLSHandshakes []*model.ArchivalTLSOrQUICHandshakeResult `json:"tls_handshakes"`
|
||||
// Individual failure aborting the test run for this address/port combo
|
||||
Failure *string `json:"failure"`
|
||||
}
|
||||
|
||||
type Measurer struct {
|
||||
|
@ -118,7 +127,7 @@ func (m Measurer) ExperimentVersion() string {
|
|||
}
|
||||
|
||||
// Manages sequential SMTP sessions to the same hostname (over different IPs)
|
||||
// don't use in parallel!
|
||||
// don't use in parallel because addr changed dynamically
|
||||
type SMTPRunner struct {
|
||||
trace *measurexlite.Trace
|
||||
logger model.Logger
|
||||
|
@ -131,19 +140,31 @@ type SMTPRunner struct {
|
|||
addr string
|
||||
}
|
||||
|
||||
func (r SMTPRunner) smtp_error(err error) {
|
||||
key := net.JoinHostPort(r.addr, r.port)
|
||||
// Key is initialized in conn() no need to check here
|
||||
r.tk.SMTPErrors[key] = append(r.tk.SMTPErrors[key], tracex.NewFailure(err))
|
||||
func (r *SMTPRunner) run_key() string {
|
||||
return net.JoinHostPort(r.addr, r.port)
|
||||
}
|
||||
|
||||
func (r SMTPRunner) resolve(host string) ([]string, bool) {
|
||||
func (r *SMTPRunner) run_error(err error) {
|
||||
r.tk.Failed = true
|
||||
key := r.run_key()
|
||||
// Key is initialized in conn() no need to check here
|
||||
entry, _ := r.tk.Runs[key]
|
||||
entry.Failure = tracex.NewFailure(err)
|
||||
r.tk.Runs[key] = entry
|
||||
}
|
||||
|
||||
func (r *SMTPRunner) global_error(err error) {
|
||||
r.tk.Failed = true
|
||||
r.tk.Failure = *tracex.NewFailure(err)
|
||||
}
|
||||
|
||||
func (r *SMTPRunner) resolve(host string) ([]string, bool) {
|
||||
r.logger.Infof("Resolving DNS for %s", host)
|
||||
resolver := r.trace.NewStdlibResolver(r.logger)
|
||||
addrs, err := resolver.LookupHost(r.ctx, host)
|
||||
r.tk.Queries = append(r.tk.Queries, r.trace.DNSLookupsFromRoundTrip()...)
|
||||
if err != nil {
|
||||
r.tk.Failure = *tracex.NewFailure(err)
|
||||
r.global_error(err)
|
||||
return []string{}, false
|
||||
}
|
||||
r.logger.Infof("Finished DNS for %s: %v", host, addrs)
|
||||
|
@ -151,38 +172,57 @@ func (r SMTPRunner) resolve(host string) ([]string, bool) {
|
|||
return addrs, true
|
||||
}
|
||||
|
||||
func (r SMTPRunner) conn(addr string) (net.Conn, bool) {
|
||||
// Initialize addr field and corresponding errors in TestKeys
|
||||
r.addr = addr
|
||||
if r.tk.SMTPErrors == nil {
|
||||
r.tk.SMTPErrors = make(map[string][]*string)
|
||||
func (r *SMTPRunner) get_run() IndividualTestKeys {
|
||||
if r.tk.Runs == nil {
|
||||
r.tk.Runs = make(map[string]IndividualTestKeys)
|
||||
}
|
||||
r.tk.SMTPErrors[net.JoinHostPort(addr, r.port)] = []*string{}
|
||||
key := r.run_key()
|
||||
val, exists := r.tk.Runs[key]
|
||||
if exists {
|
||||
return val
|
||||
} else {
|
||||
return IndividualTestKeys{}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SMTPRunner) save_run(itk IndividualTestKeys) {
|
||||
key := r.run_key()
|
||||
r.tk.Runs[key] = itk
|
||||
}
|
||||
|
||||
func (r *SMTPRunner) conn(addr string) (net.Conn, bool) {
|
||||
// Initialize addr field and corresponding errors in TestKeys
|
||||
r.logger.Infof("Establishing TCP to %s", addr)
|
||||
r.addr = addr
|
||||
run := r.get_run()
|
||||
|
||||
dialer := r.trace.NewDialerWithoutResolver(r.logger)
|
||||
conn, err := dialer.DialContext(r.ctx, "tcp", net.JoinHostPort(r.addr, r.port))
|
||||
r.tk.TCPConnect = append(r.tk.TCPConnect, r.trace.TCPConnects()...)
|
||||
conn, err := dialer.DialContext(r.ctx, "tcp", net.JoinHostPort(addr, r.port))
|
||||
run.TCPConnect = append(run.TCPConnect, r.trace.TCPConnects()...)
|
||||
if err != nil {
|
||||
r.smtp_error(err)
|
||||
r.run_error(err)
|
||||
return nil, false
|
||||
}
|
||||
r.save_run(run)
|
||||
return conn, true
|
||||
}
|
||||
|
||||
func (r SMTPRunner) handshake(conn net.Conn) (net.Conn, bool) {
|
||||
func (r *SMTPRunner) handshake(conn net.Conn) (net.Conn, bool) {
|
||||
r.logger.Infof("Starting TLS handshake with %s:%s (%s)", r.host, r.port, r.addr)
|
||||
run := r.get_run()
|
||||
thx := r.trace.NewTLSHandshakerStdlib(r.logger)
|
||||
tconn, _, err := thx.Handshake(r.ctx, conn, r.tlsconfig)
|
||||
r.tk.TLSHandshakes = append(r.tk.TLSHandshakes, r.trace.FirstTLSHandshakeOrNil())
|
||||
run.TLSHandshakes = append(run.TLSHandshakes, r.trace.FirstTLSHandshakeOrNil())
|
||||
if err != nil {
|
||||
r.smtp_error(err)
|
||||
r.run_error(err)
|
||||
return nil, false
|
||||
}
|
||||
r.save_run(run)
|
||||
r.logger.Infof("Handshake succeeded")
|
||||
return tconn, true
|
||||
}
|
||||
|
||||
func (r SMTPRunner) starttls(conn net.Conn, message string) (net.Conn, bool) {
|
||||
func (r *SMTPRunner) starttls(conn net.Conn, message string) (net.Conn, bool) {
|
||||
if message != "" {
|
||||
r.logger.Infof("Asking for StartTLS upgrade")
|
||||
conn.Write([]byte(message))
|
||||
|
@ -191,37 +231,40 @@ func (r SMTPRunner) starttls(conn net.Conn, message string) (net.Conn, bool) {
|
|||
return tconn, success
|
||||
}
|
||||
|
||||
func (r SMTPRunner) smtp(conn net.Conn, ehlo string, noop uint8) bool {
|
||||
func (r *SMTPRunner) smtp(conn net.Conn, ehlo string, noop uint8) bool {
|
||||
client, err := smtp.NewClient(conn, ehlo)
|
||||
if err != nil {
|
||||
r.smtp_error(err)
|
||||
r.run_error(err)
|
||||
return false
|
||||
}
|
||||
err = client.Hello(ehlo)
|
||||
if err != nil {
|
||||
r.smtp_error(err)
|
||||
r.run_error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
if noop > 0 {
|
||||
run := r.get_run()
|
||||
r.logger.Infof("Trying to generate more no-op traffic")
|
||||
// TODO: noop counter per IP address
|
||||
r.tk.NoOpCounter = 0
|
||||
for r.tk.NoOpCounter < noop {
|
||||
r.tk.NoOpCounter += 1
|
||||
r.logger.Infof("NoOp Iteration %d", r.tk.NoOpCounter)
|
||||
run.NoOpCounter = 0
|
||||
for run.NoOpCounter < noop {
|
||||
run.NoOpCounter += 1
|
||||
r.logger.Infof("NoOp Iteration %d", run.NoOpCounter)
|
||||
err = client.Noop()
|
||||
if err != nil {
|
||||
r.smtp_error(err)
|
||||
r.run_error(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if r.tk.NoOpCounter == noop {
|
||||
r.save_run(run)
|
||||
|
||||
if run.NoOpCounter == noop {
|
||||
r.logger.Infof("Successfully generated no-op traffic")
|
||||
return true
|
||||
} else {
|
||||
r.logger.Infof("Failed no-op traffic at iteration %d", r.tk.NoOpCounter)
|
||||
r.logger.Infof("Failed no-op traffic at iteration %d", run.NoOpCounter)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +298,7 @@ func (m Measurer) Run(
|
|||
ServerName: config.host,
|
||||
}
|
||||
|
||||
runner := SMTPRunner{
|
||||
runner := &SMTPRunner{
|
||||
trace: trace,
|
||||
logger: log,
|
||||
ctx: ctx,
|
||||
|
|
Loading…
Reference in New Issue
Block a user