-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathcontrib.go
136 lines (107 loc) · 3.26 KB
/
contrib.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Determine the bandwidth contribution of the given relays.
package main
import (
"bufio"
"fmt"
"log"
"net"
"os"
"strings"
"sync"
tor "git.torproject.org/user/phw/zoossh.git"
)
// NetblockMap maps a network name to a set of netblocks.
type NetblockMap map[string][]*net.IPNet
// Contribution keeps track of the bandwidth contribution of a network name.
type Contribution map[string]uint64
// Contains returns true if the given netblock map contains the given IP
// address. The lookup is very inefficient, but has to do for now.
func (nbm NetblockMap) Contains(ipAddr net.IP) bool {
for _, netblocks := range nbm {
for _, netblock := range netblocks {
if netblock.Contains(ipAddr) {
return true
}
}
}
return false
}
// ParseNetblocks parses the given file name, and extracts and returns all
// netblocks contained within. Lines starting with "#" are interpreted as
// netblock names. All subsequent netblocks are stored under that name.
func ParseNetblocks(fileName string) NetblockMap {
log.Printf("Attempting to parse file %s.", fileName)
fd, err := os.Open(fileName)
if err != nil {
log.Fatal(err)
}
defer fd.Close()
netblocks := make(map[string][]*net.IPNet)
netname := "default"
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
line := scanner.Text()
// New netblock name.
if strings.HasPrefix(line, "#") {
netname = strings.TrimSpace(line[1:])
continue
}
_, ipnet, err := net.ParseCIDR(line)
if err != nil {
log.Fatal(err)
}
netblocks[netname] = append(netblocks[netname], ipnet)
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
for netname, netblocks := range netblocks {
log.Printf("Parsed %d IP address blocks for %s.\n", len(netblocks), netname)
}
return netblocks
}
// BandwidthContribution determines the bandwidth contribution made by Tor
// relays whose IP address is in the given netblocks.
func BandwidthContribution(channel chan tor.ObjectSet, params *CmdLineParams, group *sync.WaitGroup) {
defer group.Done()
var totalBw, totalCount, cloudBw, cloudCount uint64
netblockMap := ParseNetblocks(params.InputData)
contribution := make(Contribution)
for netname, _ := range netblockMap {
contribution[netname] = 0
}
fmt.Println("cloudcount, totalcount, cloudbw, totalbw, bwfraction")
// Iterate over all consensuses.
for objects := range channel {
totalBw = 0
cloudBw = 0
totalCount = 0
cloudCount = 0
// Iterate over single relays in consensus.
switch v := objects.(type) {
case *tor.Consensus:
for _, getStatus := range v.RouterStatuses {
status := getStatus()
totalBw += status.Bandwidth
totalCount += 1
for netname, netblocks := range netblockMap {
for _, netblock := range netblocks {
// Is the relay cloud-hosted?
if netblock.Contains(status.Address.IPv4Address) {
contribution[netname] += status.Bandwidth
cloudBw += status.Bandwidth
cloudCount += 1
}
}
}
}
case *tor.RouterDescriptors:
log.Fatalln("Router descriptors not supported.")
}
bwfraction := float32(cloudBw) / float32(totalBw)
fmt.Printf("%d, %d, %d, %d, %.3f\n", cloudCount, totalCount, cloudBw, totalBw, bwfraction)
}
for netname, bw := range contribution {
log.Printf("%s contributed %d of bandwidth.\n", netname, bw)
}
}