1package main
2
3import (
4	"fmt"
5	"log"
6	"os"
7	"path/filepath"
8	"time"
9
10	"git.torproject.org/user/phw/zoossh.git"
11)
12
13var processedCons int64 = 0
14var processedDescs int64 = 0
15var totalExits int64 = 0
16var totalRelays int64 = 0
17var totalBw uint64 = 0
18
19func Min(a uint64, b uint64, c uint64) uint64 {
20
21	min := a
22
23	if b < min {
24		min = b
25	}
26
27	if c < min {
28		min = c
29	}
30
31	return min
32}
33
34func ProcessDescriptors(path string, info os.FileInfo, err error) error {
35
36	if _, err := os.Stat(path); err != nil {
37		return err
38	}
39
40	if info.IsDir() {
41		return nil
42	}
43
44	consensus, err := zoossh.ParseDescriptorFile(path)
45	if err != nil {
46		return err
47	}
48
49	if (processedDescs % 100) == 0 {
50		fmt.Printf(".")
51	}
52
53	for _, getDesc := range consensus.RouterDescriptors {
54		desc := getDesc()
55		totalBw += Min(desc.BandwidthAvg, desc.BandwidthBurst, desc.BandwidthObs)
56		processedDescs++
57	}
58
59	return nil
60}
61
62func ProcessConsensus(path string, info os.FileInfo, err error) error {
63
64	if _, err := os.Stat(path); err != nil {
65		return err
66	}
67
68	if info.IsDir() {
69		return nil
70	}
71
72	consensus, err := zoossh.ParseConsensusFile(path)
73	if err != nil {
74		return err
75	}
76	fmt.Printf(".")
77
78	for _, getStatus := range consensus.RouterStatuses {
79		status := getStatus()
80		totalRelays++
81		if status.Flags.Exit == true {
82			totalExits++
83		}
84	}
85	processedCons++
86
87	return nil
88}
89
90func main() {
91
92	if len(os.Args) != 3 {
93		log.Fatalf("Usage: %s CONSENSUS_ARCHIVE DESCRIPTOR_ARCHIVE", os.Args[0])
94	}
95
96	before := time.Now()
97	filepath.Walk(os.Args[1], ProcessConsensus)
98	fmt.Println()
99	after := time.Now()
100
101	duration := after.Sub(before)
102	fmt.Println("Total time for consensuses:", duration)
103	fmt.Printf("Time per consensus: %dms\n",
104		duration.Nanoseconds()/processedCons/int64(1000000))
105	fmt.Printf("Processed %d consensuses with %d router status entries.\n",
106		processedCons, totalRelays)
107	fmt.Printf("Total exits: %d\n", totalExits)
108
109	before = time.Now()
110	filepath.Walk(os.Args[2], ProcessDescriptors)
111	fmt.Println()
112	after = time.Now()
113
114	duration = after.Sub(before)
115	fmt.Println("Total time for descriptors:", duration)
116	fmt.Printf("Time per descriptor: %dns\n",
117		duration.Nanoseconds()/processedDescs)
118	fmt.Printf("Processed %d descriptors.\n", processedDescs)
119	fmt.Printf("Average advertised bandwidth: %d\n", totalBw/uint64(processedDescs))
120}
121