murder 0.0.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. data/.gitignore +1 -0
  2. data/LICENSE +17 -0
  3. data/README +224 -0
  4. data/Rakefile +52 -0
  5. data/VERSION +1 -0
  6. data/dist/BitTornado/BT1/Choker.py +128 -0
  7. data/dist/BitTornado/BT1/Connecter.py +288 -0
  8. data/dist/BitTornado/BT1/Downloader.py +594 -0
  9. data/dist/BitTornado/BT1/DownloaderFeedback.py +155 -0
  10. data/dist/BitTornado/BT1/Encrypter.py +333 -0
  11. data/dist/BitTornado/BT1/FileSelector.py +245 -0
  12. data/dist/BitTornado/BT1/Filter.py +12 -0
  13. data/dist/BitTornado/BT1/HTTPDownloader.py +251 -0
  14. data/dist/BitTornado/BT1/NatCheck.py +95 -0
  15. data/dist/BitTornado/BT1/PiecePicker.py +320 -0
  16. data/dist/BitTornado/BT1/Rerequester.py +426 -0
  17. data/dist/BitTornado/BT1/Statistics.py +177 -0
  18. data/dist/BitTornado/BT1/Storage.py +584 -0
  19. data/dist/BitTornado/BT1/StorageWrapper.py +1045 -0
  20. data/dist/BitTornado/BT1/StreamCheck.py +135 -0
  21. data/dist/BitTornado/BT1/T2T.py +193 -0
  22. data/dist/BitTornado/BT1/Uploader.py +145 -0
  23. data/dist/BitTornado/BT1/__init__.py +1 -0
  24. data/dist/BitTornado/BT1/btformats.py +100 -0
  25. data/dist/BitTornado/BT1/fakeopen.py +89 -0
  26. data/dist/BitTornado/BT1/makemetafile.py +263 -0
  27. data/dist/BitTornado/BT1/track.py +1067 -0
  28. data/dist/BitTornado/ConfigDir.py +401 -0
  29. data/dist/BitTornado/ConfigReader.py +1068 -0
  30. data/dist/BitTornado/ConnChoice.py +31 -0
  31. data/dist/BitTornado/CreateIcons.py +105 -0
  32. data/dist/BitTornado/CurrentRateMeasure.py +37 -0
  33. data/dist/BitTornado/HTTPHandler.py +167 -0
  34. data/dist/BitTornado/PSYCO.py +5 -0
  35. data/dist/BitTornado/RateLimiter.py +153 -0
  36. data/dist/BitTornado/RateMeasure.py +75 -0
  37. data/dist/BitTornado/RawServer.py +195 -0
  38. data/dist/BitTornado/ServerPortHandler.py +188 -0
  39. data/dist/BitTornado/SocketHandler.py +375 -0
  40. data/dist/BitTornado/__init__.py +63 -0
  41. data/dist/BitTornado/bencode.py +319 -0
  42. data/dist/BitTornado/bitfield.py +162 -0
  43. data/dist/BitTornado/clock.py +27 -0
  44. data/dist/BitTornado/download_bt1.py +882 -0
  45. data/dist/BitTornado/inifile.py +169 -0
  46. data/dist/BitTornado/iprangeparse.py +194 -0
  47. data/dist/BitTornado/launchmanycore.py +381 -0
  48. data/dist/BitTornado/natpunch.py +254 -0
  49. data/dist/BitTornado/parseargs.py +137 -0
  50. data/dist/BitTornado/parsedir.py +150 -0
  51. data/dist/BitTornado/piecebuffer.py +86 -0
  52. data/dist/BitTornado/selectpoll.py +109 -0
  53. data/dist/BitTornado/subnetparse.py +218 -0
  54. data/dist/BitTornado/torrentlistparse.py +38 -0
  55. data/dist/BitTornado/zurllib.py +100 -0
  56. data/dist/murder_client.py +291 -0
  57. data/dist/murder_make_torrent.py +46 -0
  58. data/dist/murder_tracker.py +28 -0
  59. data/doc/examples/Capfile +28 -0
  60. data/lib/capistrano/recipes/deploy/strategy/murder.rb +52 -0
  61. data/lib/murder.rb +43 -0
  62. data/lib/murder/admin.rb +47 -0
  63. data/lib/murder/murder.rb +121 -0
  64. data/murder.gemspec +101 -0
  65. metadata +129 -0
@@ -0,0 +1,86 @@
1
+ # Written by John Hoffman
2
+ # see LICENSE.txt for license information
3
+
4
+ from array import array
5
+ from threading import Lock
6
+ # import inspect
7
+ try:
8
+ True
9
+ except:
10
+ True = 1
11
+ False = 0
12
+
13
+ DEBUG = False
14
+
15
+ class SingleBuffer:
16
+ def __init__(self, pool):
17
+ self.pool = pool
18
+ self.buf = array('c')
19
+
20
+ def init(self):
21
+ if DEBUG:
22
+ print self.count
23
+ '''
24
+ for x in xrange(6,1,-1):
25
+ try:
26
+ f = inspect.currentframe(x).f_code
27
+ print (f.co_filename,f.co_firstlineno,f.co_name)
28
+ del f
29
+ except:
30
+ pass
31
+ print ''
32
+ '''
33
+ self.length = 0
34
+
35
+ def append(self, s):
36
+ l = self.length+len(s)
37
+ self.buf[self.length:l] = array('c',s)
38
+ self.length = l
39
+
40
+ def __len__(self):
41
+ return self.length
42
+
43
+ def __getslice__(self, a, b):
44
+ if b > self.length:
45
+ b = self.length
46
+ if b < 0:
47
+ b += self.length
48
+ if a == 0 and b == self.length and len(self.buf) == b:
49
+ return self.buf # optimization
50
+ return self.buf[a:b]
51
+
52
+ def getarray(self):
53
+ return self.buf[:self.length]
54
+
55
+ def release(self):
56
+ if DEBUG:
57
+ print -self.count
58
+ self.pool.release(self)
59
+
60
+
61
+ class BufferPool:
62
+ def __init__(self):
63
+ self.pool = []
64
+ self.lock = Lock()
65
+ if DEBUG:
66
+ self.count = 0
67
+
68
+ def new(self):
69
+ self.lock.acquire()
70
+ if self.pool:
71
+ x = self.pool.pop()
72
+ else:
73
+ x = SingleBuffer(self)
74
+ if DEBUG:
75
+ self.count += 1
76
+ x.count = self.count
77
+ x.init()
78
+ self.lock.release()
79
+ return x
80
+
81
+ def release(self, x):
82
+ self.pool.append(x)
83
+
84
+
85
+ _pool = BufferPool()
86
+ PieceBuffer = _pool.new
@@ -0,0 +1,109 @@
1
+ # Written by Bram Cohen
2
+ # see LICENSE.txt for license information
3
+
4
+ from select import select, error
5
+ from time import sleep
6
+ from types import IntType
7
+ from bisect import bisect
8
+ POLLIN = 1
9
+ POLLOUT = 2
10
+ POLLERR = 8
11
+ POLLHUP = 16
12
+
13
+ class poll:
14
+ def __init__(self):
15
+ self.rlist = []
16
+ self.wlist = []
17
+
18
+ def register(self, f, t):
19
+ if type(f) != IntType:
20
+ f = f.fileno()
21
+ if (t & POLLIN):
22
+ insert(self.rlist, f)
23
+ else:
24
+ remove(self.rlist, f)
25
+ if (t & POLLOUT):
26
+ insert(self.wlist, f)
27
+ else:
28
+ remove(self.wlist, f)
29
+
30
+ def unregister(self, f):
31
+ if type(f) != IntType:
32
+ f = f.fileno()
33
+ remove(self.rlist, f)
34
+ remove(self.wlist, f)
35
+
36
+ def poll(self, timeout = None):
37
+ if self.rlist or self.wlist:
38
+ try:
39
+ r, w, e = select(self.rlist, self.wlist, [], timeout)
40
+ except ValueError:
41
+ return None
42
+ else:
43
+ sleep(timeout)
44
+ return []
45
+ result = []
46
+ for s in r:
47
+ result.append((s, POLLIN))
48
+ for s in w:
49
+ result.append((s, POLLOUT))
50
+ return result
51
+
52
+ def remove(list, item):
53
+ i = bisect(list, item)
54
+ if i > 0 and list[i-1] == item:
55
+ del list[i-1]
56
+
57
+ def insert(list, item):
58
+ i = bisect(list, item)
59
+ if i == 0 or list[i-1] != item:
60
+ list.insert(i, item)
61
+
62
+ def test_remove():
63
+ x = [2, 4, 6]
64
+ remove(x, 2)
65
+ assert x == [4, 6]
66
+ x = [2, 4, 6]
67
+ remove(x, 4)
68
+ assert x == [2, 6]
69
+ x = [2, 4, 6]
70
+ remove(x, 6)
71
+ assert x == [2, 4]
72
+ x = [2, 4, 6]
73
+ remove(x, 5)
74
+ assert x == [2, 4, 6]
75
+ x = [2, 4, 6]
76
+ remove(x, 1)
77
+ assert x == [2, 4, 6]
78
+ x = [2, 4, 6]
79
+ remove(x, 7)
80
+ assert x == [2, 4, 6]
81
+ x = [2, 4, 6]
82
+ remove(x, 5)
83
+ assert x == [2, 4, 6]
84
+ x = []
85
+ remove(x, 3)
86
+ assert x == []
87
+
88
+ def test_insert():
89
+ x = [2, 4]
90
+ insert(x, 1)
91
+ assert x == [1, 2, 4]
92
+ x = [2, 4]
93
+ insert(x, 3)
94
+ assert x == [2, 3, 4]
95
+ x = [2, 4]
96
+ insert(x, 5)
97
+ assert x == [2, 4, 5]
98
+ x = [2, 4]
99
+ insert(x, 2)
100
+ assert x == [2, 4]
101
+ x = [2, 4]
102
+ insert(x, 4)
103
+ assert x == [2, 4]
104
+ x = [2, 3, 4]
105
+ insert(x, 3)
106
+ assert x == [2, 3, 4]
107
+ x = []
108
+ insert(x, 3)
109
+ assert x == [3]
@@ -0,0 +1,218 @@
1
+ # Written by John Hoffman
2
+ # see LICENSE.txt for license information
3
+
4
+ from bisect import bisect, insort
5
+
6
+ try:
7
+ True
8
+ except:
9
+ True = 1
10
+ False = 0
11
+ bool = lambda x: not not x
12
+
13
+ hexbinmap = {
14
+ '0': '0000',
15
+ '1': '0001',
16
+ '2': '0010',
17
+ '3': '0011',
18
+ '4': '0100',
19
+ '5': '0101',
20
+ '6': '0110',
21
+ '7': '0111',
22
+ '8': '1000',
23
+ '9': '1001',
24
+ 'a': '1010',
25
+ 'b': '1011',
26
+ 'c': '1100',
27
+ 'd': '1101',
28
+ 'e': '1110',
29
+ 'f': '1111',
30
+ 'x': '0000',
31
+ }
32
+
33
+ chrbinmap = {}
34
+ for n in xrange(256):
35
+ b = []
36
+ nn = n
37
+ for i in xrange(8):
38
+ if nn & 0x80:
39
+ b.append('1')
40
+ else:
41
+ b.append('0')
42
+ nn <<= 1
43
+ chrbinmap[n] = ''.join(b)
44
+
45
+
46
+ def to_bitfield_ipv4(ip):
47
+ ip = ip.split('.')
48
+ if len(ip) != 4:
49
+ raise ValueError, "bad address"
50
+ b = []
51
+ for i in ip:
52
+ b.append(chrbinmap[int(i)])
53
+ return ''.join(b)
54
+
55
+ def to_bitfield_ipv6(ip):
56
+ b = ''
57
+ doublecolon = False
58
+
59
+ if ip == '':
60
+ raise ValueError, "bad address"
61
+ if ip == '::': # boundary handling
62
+ ip = ''
63
+ elif ip[:2] == '::':
64
+ ip = ip[1:]
65
+ elif ip[0] == ':':
66
+ raise ValueError, "bad address"
67
+ elif ip[-2:] == '::':
68
+ ip = ip[:-1]
69
+ elif ip[-1] == ':':
70
+ raise ValueError, "bad address"
71
+ for n in ip.split(':'):
72
+ if n == '': # double-colon
73
+ if doublecolon:
74
+ raise ValueError, "bad address"
75
+ doublecolon = True
76
+ b += ':'
77
+ continue
78
+ if n.find('.') >= 0: # IPv4
79
+ n = to_bitfield_ipv4(n)
80
+ b += n + '0'*(32-len(n))
81
+ continue
82
+ n = ('x'*(4-len(n))) + n
83
+ for i in n:
84
+ b += hexbinmap[i]
85
+ if doublecolon:
86
+ pos = b.find(':')
87
+ b = b[:pos]+('0'*(129-len(b)))+b[pos+1:]
88
+ if len(b) != 128: # always check size
89
+ raise ValueError, "bad address"
90
+ return b
91
+
92
+ ipv4addrmask = to_bitfield_ipv6('::ffff:0:0')[:96]
93
+
94
+ class IP_List:
95
+ def __init__(self):
96
+ self.ipv4list = []
97
+ self.ipv6list = []
98
+
99
+ def __nonzero__(self):
100
+ return bool(self.ipv4list or self.ipv6list)
101
+
102
+
103
+ def append(self, ip, depth = 256):
104
+ if ip.find(':') < 0: # IPv4
105
+ insort(self.ipv4list,to_bitfield_ipv4(ip)[:depth])
106
+ else:
107
+ b = to_bitfield_ipv6(ip)
108
+ if b.startswith(ipv4addrmask):
109
+ insort(self.ipv4list,b[96:][:depth-96])
110
+ else:
111
+ insort(self.ipv6list,b[:depth])
112
+
113
+
114
+ def includes(self, ip):
115
+ if not (self.ipv4list or self.ipv6list):
116
+ return False
117
+ if ip.find(':') < 0: # IPv4
118
+ b = to_bitfield_ipv4(ip)
119
+ else:
120
+ b = to_bitfield_ipv6(ip)
121
+ if b.startswith(ipv4addrmask):
122
+ b = b[96:]
123
+ if len(b) > 32:
124
+ l = self.ipv6list
125
+ else:
126
+ l = self.ipv4list
127
+ for map in l[bisect(l,b)-1:]:
128
+ if b.startswith(map):
129
+ return True
130
+ if map > b:
131
+ return False
132
+ return False
133
+
134
+
135
+ def read_fieldlist(self, file): # reads a list from a file in the format 'ip/len <whatever>'
136
+ f = open(file, 'r')
137
+ while True:
138
+ line = f.readline()
139
+ if not line:
140
+ break
141
+ line = line.strip().expandtabs()
142
+ if not line or line[0] == '#':
143
+ continue
144
+ try:
145
+ line, garbage = line.split(' ',1)
146
+ except:
147
+ pass
148
+ try:
149
+ line, garbage = line.split('#',1)
150
+ except:
151
+ pass
152
+ try:
153
+ ip, depth = line.split('/')
154
+ except:
155
+ ip = line
156
+ depth = None
157
+ try:
158
+ if depth is not None:
159
+ depth = int(depth)
160
+ self.append(ip,depth)
161
+ except:
162
+ print '*** WARNING *** could not parse IP range: '+line
163
+ f.close()
164
+
165
+
166
+ def set_intranet_addresses(self):
167
+ self.append('127.0.0.1',8)
168
+ self.append('10.0.0.0',8)
169
+ self.append('172.16.0.0',12)
170
+ self.append('192.168.0.0',16)
171
+ self.append('169.254.0.0',16)
172
+ self.append('::1')
173
+ self.append('fe80::',16)
174
+ self.append('fec0::',16)
175
+
176
+ def set_ipv4_addresses(self):
177
+ self.append('::ffff:0:0',96)
178
+
179
+ def ipv6_to_ipv4(ip):
180
+ ip = to_bitfield_ipv6(ip)
181
+ if not ip.startswith(ipv4addrmask):
182
+ raise ValueError, "not convertible to IPv4"
183
+ ip = ip[-32:]
184
+ x = ''
185
+ for i in range(4):
186
+ x += str(int(ip[:8],2))
187
+ if i < 3:
188
+ x += '.'
189
+ ip = ip[8:]
190
+ return x
191
+
192
+ def to_ipv4(ip):
193
+ if is_ipv4(ip):
194
+ _valid_ipv4(ip)
195
+ return ip
196
+ return ipv6_to_ipv4(ip)
197
+
198
+ def is_ipv4(ip):
199
+ return ip.find(':') < 0
200
+
201
+ def _valid_ipv4(ip):
202
+ ip = ip.split('.')
203
+ if len(ip) != 4:
204
+ raise ValueError
205
+ for i in ip:
206
+ chr(int(i))
207
+
208
+ def is_valid_ip(ip):
209
+ try:
210
+ if not ip:
211
+ return False
212
+ if is_ipv4(ip):
213
+ _valid_ipv4(ip)
214
+ return True
215
+ to_bitfield_ipv6(ip)
216
+ return True
217
+ except:
218
+ return False
@@ -0,0 +1,38 @@
1
+ # Written by John Hoffman
2
+ # see LICENSE.txt for license information
3
+
4
+ from binascii import unhexlify
5
+
6
+ try:
7
+ True
8
+ except:
9
+ True = 1
10
+ False = 0
11
+
12
+
13
+ # parses a list of torrent hashes, in the format of one hash per line in hex format
14
+
15
+ def parsetorrentlist(filename, parsed):
16
+ new_parsed = {}
17
+ added = {}
18
+ removed = parsed
19
+ f = open(filename, 'r')
20
+ while True:
21
+ l = f.readline()
22
+ if not l:
23
+ break
24
+ l = l.strip()
25
+ try:
26
+ if len(l) != 40:
27
+ raise ValueError, 'bad line'
28
+ h = unhexlify(l)
29
+ except:
30
+ print '*** WARNING *** could not parse line in torrent list: '+l
31
+ if parsed.has_key(h):
32
+ del removed[h]
33
+ else:
34
+ added[h] = True
35
+ new_parsed[h] = True
36
+ f.close()
37
+ return (new_parsed, added, removed)
38
+