tor-commits
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 216106 discussions
[ooni-probe/master] Rename super long function do something more human.
by art@torproject.org 21 Jul '12
by art@torproject.org 21 Jul '12
21 Jul '12
commit 3fb8b8150c1e9da4d9f0e7e1b8614db45146e265
Author: Arturo Filastò <art(a)torproject.org>
Date: Sat Jul 21 13:39:00 2012 +0200
Rename super long function do something more human.
---
ooni/plugins/daphn3.py | 2 +-
ooni/protocols/daphn3.py | 2 +-
oonib/backends/daphn3.py | 4 ++++
oonib/oonibackend.conf | 2 +-
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/ooni/plugins/daphn3.py b/ooni/plugins/daphn3.py
index 6dd9da2..82a3331 100644
--- a/ooni/plugins/daphn3.py
+++ b/ooni/plugins/daphn3.py
@@ -70,7 +70,7 @@ class daphn3Test(OONITest):
return
#pass
self.factory = Daphn3ClientFactory()
- self.steps = daphn3.get_daphn3_dictionary_from_pcap(self.local_options['pcap'])
+ self.steps = daphn3.read_pcap(self.local_options['pcap'])
def control(self, exp_res, args):
mutation = self.factory.mutator.get_mutation(0)
diff --git a/ooni/protocols/daphn3.py b/ooni/protocols/daphn3.py
index d8290e6..093929b 100644
--- a/ooni/protocols/daphn3.py
+++ b/ooni/protocols/daphn3.py
@@ -8,7 +8,7 @@ import sys
from scapy.all import *
import yaml
-def get_daphn3_dictionary_from_pcap(filename):
+def read_pcap(filename):
"""
@param filename: Filesystem path to the pcap.
diff --git a/oonib/backends/daphn3.py b/oonib/backends/daphn3.py
index a8290e3..59bdeea 100644
--- a/oonib/backends/daphn3.py
+++ b/oonib/backends/daphn3.py
@@ -1,8 +1,11 @@
from twisted.internet import protocol
from twisted.internet.error import ConnectionDone
+from oonib.common import config
+
from ooni.plugoo import reports
from ooni.protocols.daphn3 import Mutator, Daphn3Protocol
+from ooni.protocols.daphn3 import read_pcap
class Daphn3Server(protocol.ServerFactory):
"""
@@ -18,6 +21,7 @@ class Daphn3Server(protocol.ServerFactory):
def buildProtocol(self, addr):
p = self.protocol()
p.factory = self
+ p.factory.steps = read_pcap(config.daphn3.pcap_file)
if addr.host not in self.mutations:
self.mutations[addr.host] = Mutator(p.steps)
diff --git a/oonib/oonibackend.conf b/oonib/oonibackend.conf
index 3ccfdef..5265045 100644
--- a/oonib/oonibackend.conf
+++ b/oonib/oonibackend.conf
@@ -5,4 +5,4 @@ dns_tcp_port = 8002
daphn3_port = 9666
server_version = Apache
[daphn3]
-pcap_file = server.pcap
+pcap_file = /Users/y/Documents/workspace/ooni-probe.new/oonib/server.pcap
1
0
21 Jul '12
commit 015dfb03d7034c18875ba16d51bd2b34d29acf91
Author: Translation commit bot <translation(a)torproject.org>
Date: Sat Jul 21 05:45:09 2012 +0000
Update translations for vidalia
---
zh_CN/vidalia_zh_CN.po | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/zh_CN/vidalia_zh_CN.po b/zh_CN/vidalia_zh_CN.po
index 06f5511..d88827b 100644
--- a/zh_CN/vidalia_zh_CN.po
+++ b/zh_CN/vidalia_zh_CN.po
@@ -1,5 +1,6 @@
#
# Translators:
+# Christopher Meng <cickumqt(a)gmail.com>, 2012.
# Curtis Stone <cstone(a)fastmail.cn>, 2012.
# Kevin Chen <szescxz(a)126.com>, 2011.
# runasand <runa.sandvik(a)gmail.com>, 2011.
@@ -9,8 +10,8 @@ msgstr ""
"Project-Id-Version: The Tor Project\n"
"Report-Msgid-Bugs-To: https://trac.torproject.org/projects/tor\n"
"POT-Creation-Date: 2012-03-21 17:52+0000\n"
-"PO-Revision-Date: 2012-06-05 11:54+0000\n"
-"Last-Translator: Curtis Stone <cstone(a)fastmail.cn>\n"
+"PO-Revision-Date: 2012-07-21 05:21+0000\n"
+"Last-Translator: Christopher Meng <cickumqt(a)gmail.com>\n"
"Language-Team: translations(a)vidalia-project.net\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -2092,11 +2093,11 @@ msgstr ""
msgctxt "MainWindow"
msgid "(probably Telnet)"
-msgstr ""
+msgstr "(可能是 Telnet)"
msgctxt "MainWindow"
msgid "(probably an email client)"
-msgstr ""
+msgstr "(可能是邮件客户端)"
msgctxt "MainWindow"
msgid ""
@@ -2692,7 +2693,7 @@ msgstr "HTTP / HTTPS"
msgctxt "NetworkPage"
msgid "You must specify one or more bridges."
-msgstr ""
+msgstr "您必须指定一个或多个网桥。"
msgctxt "Policy"
msgid "accept"
1
0
21 Jul '12
commit 0b318874ece957c8f27e129033ed70e78b4438f9
Author: Arturo Filastò <art(a)torproject.org>
Date: Sat Jul 21 02:45:36 2012 +0200
Move configuration code into common.
---
oonib/common.py | 6 ++++++
oonib/oonibackend.conf | 3 ++-
oonib/oonibackend.py | 10 ++--------
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/oonib/common.py b/oonib/common.py
new file mode 100644
index 0000000..2f1b6f9
--- /dev/null
+++ b/oonib/common.py
@@ -0,0 +1,6 @@
+from ooni.utils import Storage
+from ooni.utils.config import Config
+
+config = Storage()
+config.main = Config('main', 'oonibackend.conf')
+config.daphn3 = Config('daphn3', 'oonibackend.conf')
diff --git a/oonib/oonibackend.conf b/oonib/oonibackend.conf
index 864df1e..3ccfdef 100644
--- a/oonib/oonibackend.conf
+++ b/oonib/oonibackend.conf
@@ -3,5 +3,6 @@ http_port = 8080
dns_udp_port = 5354
dns_tcp_port = 8002
daphn3_port = 9666
+server_version = Apache
[daphn3]
-pcap_file = 'server.pcap'
+pcap_file = server.pcap
diff --git a/oonib/oonibackend.py b/oonib/oonibackend.py
index 2ad7f34..fe1a760 100755
--- a/oonib/oonibackend.py
+++ b/oonib/oonibackend.py
@@ -16,19 +16,13 @@ from twisted.web import resource, server, static
from twisted.web.microdom import escape
from twisted.names import dns
-from ooni.utils import Storage
-from ooni.utils.config import Config
-
+from oonib.common import config
from oonib.backends.http import HTTPBackend
from oonib.backends.dns import ProxyDNSServer
from oonib.backends.daphn3 import Daphn3Server
-config = Storage()
-config.main = Config('main', 'oonibackend.conf')
-config.daphn3 = Config('daphn3', 'oonibackend.conf')
-
# This tells twisted to set the
-server.version = "Apache"
+server.version = config.main.server_version
application = service.Application('oonibackend')
serviceCollection = service.IServiceCollection(application)
1
0
21 Jul '12
commit 198a635527a8afd4bbd9606c0925f740ae6f0df9
Author: Arturo Filastò <art(a)torproject.org>
Date: Sat Jul 21 02:41:55 2012 +0200
Add support for config file for OONIB.
Refactor backend code.
---
ooni/utils/config.py | 2 +-
oonib/backends/daphn3.py | 33 +++++++++++++++++++
oonib/backends/dns.py | 16 +++++++++
oonib/backends/http.py | 74 ++++++++++++++++++++++++++++++++++++++++++++
oonib/daphn3.py | 33 -------------------
oonib/dnsbackend.py | 16 ---------
oonib/httpbackend.py | 74 --------------------------------------------
oonib/oonibackend.conf | 7 ++++
oonib/oonibackend.py | 21 ++++++++----
9 files changed, 145 insertions(+), 131 deletions(-)
diff --git a/ooni/utils/config.py b/ooni/utils/config.py
index 42a14f6..ab43e66 100644
--- a/ooni/utils/config.py
+++ b/ooni/utils/config.py
@@ -1,5 +1,5 @@
import ConfigParser
-from utils import Storage
+from ooni.utils import Storage
class Config(Storage):
"""
diff --git a/oonib/backends/__init__.py b/oonib/backends/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/oonib/backends/daphn3.py b/oonib/backends/daphn3.py
new file mode 100644
index 0000000..a8290e3
--- /dev/null
+++ b/oonib/backends/daphn3.py
@@ -0,0 +1,33 @@
+from twisted.internet import protocol
+from twisted.internet.error import ConnectionDone
+
+from ooni.plugoo import reports
+from ooni.protocols.daphn3 import Mutator, Daphn3Protocol
+
+class Daphn3Server(protocol.ServerFactory):
+ """
+ This is the main class that deals with the daphn3 server side component.
+ We keep track of global state of every client here.
+ Every client is identified by their IP address and the state of mutation is
+ stored by using their IP address as a key. This may lead to some bugs if
+ two different clients are sharing the same IP, but hopefully the
+ probability of such thing is not that likely.
+ """
+ protocol = Daphn3Protocol
+ mutations = {}
+ def buildProtocol(self, addr):
+ p = self.protocol()
+ p.factory = self
+
+ if addr.host not in self.mutations:
+ self.mutations[addr.host] = Mutator(p.steps)
+ else:
+ print "Moving on to next mutation"
+ if not self.mutations[addr.host].next_mutation():
+ self.mutations.pop(addr.host)
+ try:
+ p.mutator = self.mutations[addr.host]
+ except:
+ pass
+ return p
+
diff --git a/oonib/backends/dns.py b/oonib/backends/dns.py
new file mode 100644
index 0000000..689d1a4
--- /dev/null
+++ b/oonib/backends/dns.py
@@ -0,0 +1,16 @@
+from twisted.internet.protocol import Factory, Protocol
+from twisted.internet import reactor
+from twisted.names import dns
+from twisted.names import client, server
+
+class ProxyDNSServer(server.DNSServerFactory):
+ def __init__(self, authorities = None,
+ caches = None, clients = None,
+ verbose = 0):
+ resolver = client.Resolver(servers=[('8.8.8.8', 53)])
+ server.DNSServerFactory.__init__(self, authorities = authorities,
+ caches = caches, clients = [resolver],
+ verbose = verbose)
+ def handleQuery(self, message, protocol, address):
+ print message, protocol, address
+ server.DNSServerFactory.handleQuery(self, message, protocol, address)
diff --git a/oonib/backends/http.py b/oonib/backends/http.py
new file mode 100644
index 0000000..79a487b
--- /dev/null
+++ b/oonib/backends/http.py
@@ -0,0 +1,74 @@
+import json
+import random
+import string
+
+from twisted.application import internet, service
+from twisted.internet import protocol, reactor, defer
+from twisted.protocols import basic
+from twisted.web import resource, server, static
+from twisted.web.microdom import escape
+
+server.version = "Apache"
+
+class HTTPRandomPage(resource.Resource):
+ """
+ This generates a random page of arbitrary length and containing the string
+ selected by the user.
+ The format is the following:
+ /random/<length>/<keyword>
+ """
+ isLeaf = True
+ def _gen_random_string(self, length):
+ return ''.join(random.choice(string.letters) for x in range(length))
+
+ def genRandomPage(self, length=100, keyword=None):
+ data = self._gen_random_string(length/2)
+ if keyword:
+ data += keyword
+ data += self._gen_random_string(length - length/2)
+ data += '\n'
+ return data
+
+ def render(self, request):
+ length = 100
+ keyword = None
+ path_parts = request.path.split('/')
+ if len(path_parts) > 2:
+ length = int(path_parts[2])
+ if length > 100000:
+ length = 100000
+
+ if len(path_parts) > 3:
+ keyword = escape(path_parts[3])
+
+ return self.genRandomPage(length, keyword)
+
+class HTTPReturnHeaders(resource.Resource):
+ """
+ This returns the headers being sent by the client in JSON format.
+ """
+ isLeaf = True
+ def render(self, request):
+ req_headers = request.getAllHeaders()
+ return json.dumps(req_headers)
+
+class HTTPSendHeaders(resource.Resource):
+ """
+ This sends to the client the headers that they send inside of the POST
+ request encoded in json.
+ """
+ isLeaf = True
+ def render_POST(self, request):
+ headers = json.loads(request.content.read())
+ for header, value in headers.items():
+ request.setHeader(str(header), str(value))
+ return ''
+
+class HTTPBackend(resource.Resource):
+ def __init__(self):
+ resource.Resource.__init__(self)
+ self.putChild('random', HTTPRandomPage())
+ self.putChild('returnheaders', HTTPReturnHeaders())
+ self.putChild('sendheaders', HTTPSendHeaders())
+
+
diff --git a/oonib/daphn3.py b/oonib/daphn3.py
deleted file mode 100644
index 22aef49..0000000
--- a/oonib/daphn3.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from twisted.internet import protocol
-from twisted.internet.error import ConnectionDone
-
-from ooni.plugoo import reports
-from ooni.protocols.daphn3 import Mutator, daphn3Protocol
-
-class daphn3Server(protocol.ServerFactory):
- """
- This is the main class that deals with the daphn3 server side component.
- We keep track of global state of every client here.
- Every client is identified by their IP address and the state of mutation is
- stored by using their IP address as a key. This may lead to some bugs if
- two different clients are sharing the same IP, but hopefully the
- probability of such thing is not that likely.
- """
- protocol = daphn3Protocol
- mutations = {}
- def buildProtocol(self, addr):
- p = self.protocol()
- p.factory = self
-
- if addr.host not in self.mutations:
- self.mutations[addr.host] = Mutator(p.steps)
- else:
- print "Moving on to next mutation"
- if not self.mutations[addr.host].next_mutation():
- self.mutations.pop(addr.host)
- try:
- p.mutator = self.mutations[addr.host]
- except:
- pass
- return p
-
diff --git a/oonib/dnsbackend.py b/oonib/dnsbackend.py
deleted file mode 100644
index 689d1a4..0000000
--- a/oonib/dnsbackend.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from twisted.internet.protocol import Factory, Protocol
-from twisted.internet import reactor
-from twisted.names import dns
-from twisted.names import client, server
-
-class ProxyDNSServer(server.DNSServerFactory):
- def __init__(self, authorities = None,
- caches = None, clients = None,
- verbose = 0):
- resolver = client.Resolver(servers=[('8.8.8.8', 53)])
- server.DNSServerFactory.__init__(self, authorities = authorities,
- caches = caches, clients = [resolver],
- verbose = verbose)
- def handleQuery(self, message, protocol, address):
- print message, protocol, address
- server.DNSServerFactory.handleQuery(self, message, protocol, address)
diff --git a/oonib/httpbackend.py b/oonib/httpbackend.py
deleted file mode 100644
index 79a487b..0000000
--- a/oonib/httpbackend.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import json
-import random
-import string
-
-from twisted.application import internet, service
-from twisted.internet import protocol, reactor, defer
-from twisted.protocols import basic
-from twisted.web import resource, server, static
-from twisted.web.microdom import escape
-
-server.version = "Apache"
-
-class HTTPRandomPage(resource.Resource):
- """
- This generates a random page of arbitrary length and containing the string
- selected by the user.
- The format is the following:
- /random/<length>/<keyword>
- """
- isLeaf = True
- def _gen_random_string(self, length):
- return ''.join(random.choice(string.letters) for x in range(length))
-
- def genRandomPage(self, length=100, keyword=None):
- data = self._gen_random_string(length/2)
- if keyword:
- data += keyword
- data += self._gen_random_string(length - length/2)
- data += '\n'
- return data
-
- def render(self, request):
- length = 100
- keyword = None
- path_parts = request.path.split('/')
- if len(path_parts) > 2:
- length = int(path_parts[2])
- if length > 100000:
- length = 100000
-
- if len(path_parts) > 3:
- keyword = escape(path_parts[3])
-
- return self.genRandomPage(length, keyword)
-
-class HTTPReturnHeaders(resource.Resource):
- """
- This returns the headers being sent by the client in JSON format.
- """
- isLeaf = True
- def render(self, request):
- req_headers = request.getAllHeaders()
- return json.dumps(req_headers)
-
-class HTTPSendHeaders(resource.Resource):
- """
- This sends to the client the headers that they send inside of the POST
- request encoded in json.
- """
- isLeaf = True
- def render_POST(self, request):
- headers = json.loads(request.content.read())
- for header, value in headers.items():
- request.setHeader(str(header), str(value))
- return ''
-
-class HTTPBackend(resource.Resource):
- def __init__(self):
- resource.Resource.__init__(self)
- self.putChild('random', HTTPRandomPage())
- self.putChild('returnheaders', HTTPReturnHeaders())
- self.putChild('sendheaders', HTTPSendHeaders())
-
-
diff --git a/oonib/oonibackend.conf b/oonib/oonibackend.conf
new file mode 100644
index 0000000..864df1e
--- /dev/null
+++ b/oonib/oonibackend.conf
@@ -0,0 +1,7 @@
+[main]
+http_port = 8080
+dns_udp_port = 5354
+dns_tcp_port = 8002
+daphn3_port = 9666
+[daphn3]
+pcap_file = 'server.pcap'
diff --git a/oonib/oonibackend.py b/oonib/oonibackend.py
index 22a8728..2ad7f34 100755
--- a/oonib/oonibackend.py
+++ b/oonib/oonibackend.py
@@ -16,23 +16,30 @@ from twisted.web import resource, server, static
from twisted.web.microdom import escape
from twisted.names import dns
-from oonib.httpbackend import HTTPBackend
-from oonib.dnsbackend import ProxyDNSServer
-from oonib.daphn3 import Daphn3Server
+from ooni.utils import Storage
+from ooni.utils.config import Config
+
+from oonib.backends.http import HTTPBackend
+from oonib.backends.dns import ProxyDNSServer
+from oonib.backends.daphn3 import Daphn3Server
+
+config = Storage()
+config.main = Config('main', 'oonibackend.conf')
+config.daphn3 = Config('daphn3', 'oonibackend.conf')
# This tells twisted to set the
server.version = "Apache"
application = service.Application('oonibackend')
serviceCollection = service.IServiceCollection(application)
-internet.TCPServer(2000, server.Site(HTTPBackend())).setServiceParent(serviceCollection)
+internet.TCPServer(int(config.main.http_port), server.Site(HTTPBackend())).setServiceParent(serviceCollection)
# Start the DNS Server related services
TCPDNSServer = ProxyDNSServer()
-internet.TCPServer(8002, TCPDNSServer).setServiceParent(serviceCollection)
+internet.TCPServer(int(config.main.dns_tcp_port), TCPDNSServer).setServiceParent(serviceCollection)
UDPFactory = dns.DNSDatagramProtocol(TCPDNSServer)
-internet.UDPServer(5354, UDPFactory).setServiceParent(serviceCollection)
+internet.UDPServer(int(config.main.dns_udp_port), UDPFactory).setServiceParent(serviceCollection)
# Start the ooni backend thing
daphn3 = Daphn3Server()
-internet.TCPServer(9666, daphn3).setServiceParent(serviceCollection)
+internet.TCPServer(int(config.main.daphn3_port), daphn3).setServiceParent(serviceCollection)
1
0
[ooni-probe/master] Merge branch 'master' of ssh://git-rw.torproject.org/ooni-probe
by art@torproject.org 21 Jul '12
by art@torproject.org 21 Jul '12
21 Jul '12
commit 2f78b37b46bedf34534fdb0ab52980b6dbe473c2
Merge: b25e217 29dccd1
Author: Arturo Filastò <hellais(a)torproject.org>
Date: Sat Jul 21 02:34:38 2012 +0200
Merge branch 'master' of ssh://git-rw.torproject.org/ooni-probe
ooni/assets/redirects.yaml | 17 +++
ooni/plugins/b0wser.py | 100 ----------------
ooni/plugins/daphn3.py | 100 ++++++++++++++++
ooni/plugins/httpt.py | 54 ++++++++-
ooni/protocols/b0wser.py | 284 --------------------------------------------
ooni/protocols/daphn3.py | 284 ++++++++++++++++++++++++++++++++++++++++++++
ooni/protocols/http.py | 17 +++
oonib/b0wser.py | 33 -----
oonib/daphn3.py | 33 +++++
oonib/oonibackend.py | 6 +-
10 files changed, 507 insertions(+), 421 deletions(-)
1
0
[ooni-probe/master] Move scapy to scapyproto to avoid breaking import of scapy from
by art@torproject.org 21 Jul '12
by art@torproject.org 21 Jul '12
21 Jul '12
commit b25e21745ecdc5c03b3229ba77ee51b5fdd1561d
Author: Arturo Filastò <hellais(a)torproject.org>
Date: Sat Jul 21 02:33:48 2012 +0200
Move scapy to scapyproto to avoid breaking import of scapy from
inside of protocols
---
ooni/protocols/scapyproto.py | 55 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/ooni/protocols/scapyproto.py b/ooni/protocols/scapyproto.py
new file mode 100644
index 0000000..4166146
--- /dev/null
+++ b/ooni/protocols/scapyproto.py
@@ -0,0 +1,55 @@
+import random
+from zope.interface import implements
+from twisted.python import usage
+from twisted.plugin import IPlugin
+from twisted.internet import protocol, defer
+from ooni.plugoo.tests import ITest, OONITest
+from ooni.plugoo.assets import Asset
+from ooni.utils import log
+
+from ooni.lib.txscapy import txsr, txsend
+
+class ScapyTest(OONITest):
+ """
+ A utility class for writing scapy driven OONI tests.
+ """
+
+ receive = True
+ timeout = None
+ pcapfile = 'scapytest.pcap'
+ def initialize(self, reactor=None):
+
+ if not self.reactor:
+ from twisted.internet import reactor
+ self.reactor = reactor
+
+ self.request = {}
+ self.response = {}
+
+ def experiment(self, args):
+ log.msg("Running experiment")
+ if self.receive:
+ log.msg("Sending and receiving packets.")
+ d = txsr(self.build_packets(), pcapfile=self.pcapfile,
+ timeout=self.timeout)
+ else:
+ log.msg("Sending packets.")
+ d = txsend(self.build_packets())
+
+ def finished(data):
+ log.msg("Finished sending")
+ return data
+
+ d.addCallback(finished)
+ return d
+
+ def build_packets(self):
+ """
+ Override this method to build scapy packets.
+ """
+ from scapy.all import IP, TCP
+ return IP()/TCP()
+
+ def load_assets(self):
+ return {}
+
1
0
commit c5a44ff8140917674ceb746bc6dd7b3a264943ee
Author: Tomás Touceda <chiiph(a)torproject.org>
Date: Fri Jul 20 20:45:05 2012 -0300
Improve bwgraph plugin
- Add a working alwaysOnTop setting
- Toggle buttons along with hiding/showing their corresponding frame
---
bwgraph/bwgraph.js | 21 ++++++++++++++++++++-
1 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/bwgraph/bwgraph.js b/bwgraph/bwgraph.js
index 565d6a0..a733b58 100644
--- a/bwgraph/bwgraph.js
+++ b/bwgraph/bwgraph.js
@@ -56,7 +56,6 @@ var bwgraph = {
file.open(QIODevice.ReadOnly);
this.widget = loader.load(file);
var layout = new QVBoxLayout(this.tab);
- vdebug(layout);
layout.sizeConstraint = QLayout.SetMinAndMaxSize;
layout.addWidget(this.widget, 100, Qt.AlignCenter);
this.tab.setLayout(layout);
@@ -112,6 +111,15 @@ var bwgraph = {
this.frame.showRecv = (this.chkReceiveRate.checkState() == Qt.Checked);
this.frame.showSend = (this.chkSendRate.checkState() == Qt.Checked);
this.toggleSettings(false);
+ if(this.chkAlwaysOnTop.checkState() == Qt.Checked)
+ {
+ this.tab.setWindowFlags(Qt.WindowFlags(this.tab.windowFlags() ^ Qt.WindowStaysOnTopHint));
+ if(this.tab.visible)
+ {
+ this.tab.show();
+ this.tab.activateWindow();
+ }
+ }
},
loadSettings: function() {
@@ -127,6 +135,15 @@ var bwgraph = {
this.cmbGraphStyle.currentIndex = this.frame.graphStyle;
this.frame.showRecv = dorecv;
this.frame.showSend = dosend;
+ if(this.chkAlwaysOnTop.checkState() == Qt.Checked)
+ {
+ this.tab.setWindowFlags(Qt.WindowFlags(this.tab.windowFlags() ^ Qt.WindowStaysOnTopHint));
+ if(this.tab.visible)
+ {
+ this.tab.show();
+ this.tab.activateWindow();
+ }
+ }
},
buildGUI: function() {
@@ -136,10 +153,12 @@ var bwgraph = {
toggleHistory: function(toggle) {
this.grpBandwidth.setVisible(toggle);
+ this.btnHistory.checked = toggle;
},
toggleSettings: function(toggle) {
this.frmSettings.setVisible(toggle);
+ this.btnSettings.checked = toggle;
},
stop: function() {
1
0
[vidalia-plugins/master] Add bandwidth graph implementation as a plugin
by chiiph@torproject.org 20 Jul '12
by chiiph@torproject.org 20 Jul '12
20 Jul '12
commit f64298fbeb7cc576f43bb00f3c0b6715dc63d385
Author: Tomás Touceda <chiiph(a)torproject.org>
Date: Fri Jul 20 15:14:26 2012 -0300
Add bandwidth graph implementation as a plugin
---
bwgraph/bwgraph.js | 149 +++++++++++++++
bwgraph/bwgraph.ui | 485 +++++++++++++++++++++++++++++++++++++++++++++++++
bwgraph/graphframe.js | 297 ++++++++++++++++++++++++++++++
bwgraph/info.xml | 11 +
4 files changed, 942 insertions(+), 0 deletions(-)
diff --git a/bwgraph/bwgraph.js b/bwgraph/bwgraph.js
new file mode 100644
index 0000000..565d6a0
--- /dev/null
+++ b/bwgraph/bwgraph.js
@@ -0,0 +1,149 @@
+importExtension("qt");
+importExtension("qt.core");
+importExtension("qt.gui");
+importExtension("qt.uitools");
+
+var bwgraph = {
+ From: "From",
+ Sent: "Sent",
+ Recv: "Recv",
+
+ SETTING_DORECV: "DoRecv",
+ SETTING_DOSEND: "DoSend",
+ SETTING_ALWAYS_ON_TOP: "AlwaysOnTop",
+ SETTING_STYLE: "GraphStyle",
+
+ start: function() {
+ vdebug("Bwhistory@start");
+ torControl["bandwidthUpdate(quint64, quint64)"].connect(this, this.saveBandwidth);
+ this.createGUI();
+ this.loadSettings();
+
+ this.recv = parseInt(this.tab.getSetting(this.Sent, 0));
+ this.sent = parseInt(this.tab.getSetting(this.Recv, 0));
+ this.from = this.tab.getSetting(this.From, "");
+
+ if(this.from.length == 0)
+ this.from = QDateTime.currentDateTime().toString();
+ },
+
+ saveBandwidth: function(recv, sent) {
+ this.recv += recv;
+ this.sent += sent;
+
+ this.tab.saveSetting(this.Recv, this.recv.toString());
+ this.tab.saveSetting(this.Sent, this.sent.toString());
+ this.tab.saveSetting(this.From, this.from);
+
+ this.lblFrom.text = this.from;
+ this.lblSent.text = (this.sent/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+ this.lblRecv.text = (this.recv/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+ this.frame.addPoints(recv/1024.0, sent/1024.0);
+ },
+
+ resetCounters: function() {
+ this.recv = 0;
+ this.sent = 0;
+ this.from = QDateTime.currentDateTime().toString();
+ this.saveBandwidth(0,0);
+ },
+
+ createGUI: function() {
+ this.tab = new VidaliaTab("Bandwidth Graph", "BandwidthGraph");
+
+ var file = new QFile(pluginPath+"/bwgraph/bwgraph.ui");
+ var loader = new QUiLoader(this.tab);
+ file.open(QIODevice.ReadOnly);
+ this.widget = loader.load(file);
+ var layout = new QVBoxLayout(this.tab);
+ vdebug(layout);
+ layout.sizeConstraint = QLayout.SetMinAndMaxSize;
+ layout.addWidget(this.widget, 100, Qt.AlignCenter);
+ this.tab.setLayout(layout);
+ file.close();
+
+ this.grpBandwidth = this.widget.children()[findWidget(this.widget, "grpBandwidth")];
+
+ var graphFrame = this.widget.children()[findWidget(this.widget, "graphFrame")];
+ var graphLayout = graphFrame.children()[findWidget(graphFrame, "graphLayout")];
+
+ this.frame = new GraphFrame();
+ graphLayout.addWidget(this.frame, 1000, Qt.AlignLeft);
+
+ this.btnHistory = this.widget.children()[findWidget(this.widget, "btnHistory")];
+ this.btnSettings = this.widget.children()[findWidget(this.widget, "btnSettings")];
+ this.btnReset = this.widget.children()[findWidget(this.widget, "btnReset")];
+
+ this.frmSettings = this.widget.children()[findWidget(this.widget, "frmSettings")];
+ this.btnSaveSettings = this.frmSettings.children()[findWidget(this.frmSettings, "btnSaveSettings")];
+ this.btnCancelSettings = this.frmSettings.children()[findWidget(this.frmSettings, "btnCancelSettings")];
+ this.cmbGraphStyle = this.frmSettings.children()[findWidget(this.frmSettings, "cmbGraphStyle")];
+ this.chkReceiveRate = this.frmSettings.children()[findWidget(this.frmSettings, "chkReceiveRate")];
+ this.chkSendRate = this.frmSettings.children()[findWidget(this.frmSettings, "chkSendRate")];
+ this.chkAlwaysOnTop = this.frmSettings.children()[findWidget(this.frmSettings, "chkAlwaysOnTop")];
+
+ this.lblFrom = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "lblFrom")];
+ this.lblSent = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "lblSent")];
+ this.lblRecv = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "lblRecv")];
+ this.btnResetHistory = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "btnResetHistory")];
+
+ this.lblFrom.text = this.from;
+ this.lblSent.text = (this.sent/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+ this.lblRecv.text = (this.recv/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+
+ this.btnResetHistory["clicked()"].connect(this, this.resetCounters);
+
+ this.btnHistory["toggled(bool)"].connect(this, this.toggleHistory);
+ this.btnSettings["toggled(bool)"].connect(this, this.toggleSettings);
+ this.toggleHistory(false);
+ this.toggleSettings(false);
+
+ this.btnReset["clicked()"].connect(this.frame, this.frame.resetGraph);
+ this.btnSaveSettings["clicked()"].connect(this, this.saveSettings);
+ },
+
+ saveSettings: function() {
+ vdebug("Bwhistory@saveSettings");
+ this.tab.saveSetting(this.SETTING_DORECV, (this.chkReceiveRate.checkState() == Qt.Checked) ? "true" : "false");
+ this.tab.saveSetting(this.SETTING_DOSEND, (this.chkSendRate.checkState() == Qt.Checked) ? "true" : "false");
+ this.tab.saveSetting(this.SETTING_STYLE, this.cmbGraphStyle.currentIndex);
+ this.tab.saveSetting(this.SETTING_ALWAYS_ON_TOP, (this.chkAlwaysOnTop.checkState() == Qt.Checked) ? "true" : "false");
+ this.frame.graphStyle = this.cmbGraphStyle.currentIndex;
+ this.frame.showRecv = (this.chkReceiveRate.checkState() == Qt.Checked);
+ this.frame.showSend = (this.chkSendRate.checkState() == Qt.Checked);
+ this.toggleSettings(false);
+ },
+
+ loadSettings: function() {
+ vdebug("Bwhistory@loadSettings");
+ var dorecv = this.tab.getSetting(this.SETTING_DORECV, "true") != "false";
+ var dosend = this.tab.getSetting(this.SETTING_DOSEND, "true") != "false";
+ this.frame.graphStyle = this.tab.getSetting(this.SETTING_STYLE, 0);
+ var alwaysontop = this.tab.getSetting(this.SETTING_ALWAYS_ON_TOP, "false") != "false";
+
+ this.chkReceiveRate.setCheckState(dorecv ? Qt.Checked : Qt.Unchecked);
+ this.chkSendRate.setCheckState(dosend ? Qt.Checked : Qt.Unchecked);
+ this.chkAlwaysOnTop.setCheckState(alwaysontop ? Qt.Checked : Qt.Unchecked);
+ this.cmbGraphStyle.currentIndex = this.frame.graphStyle;
+ this.frame.showRecv = dorecv;
+ this.frame.showSend = dosend;
+ },
+
+ buildGUI: function() {
+ vdebug("Bwhistory@buildGUI");
+ return this.tab;
+ },
+
+ toggleHistory: function(toggle) {
+ this.grpBandwidth.setVisible(toggle);
+ },
+
+ toggleSettings: function(toggle) {
+ this.frmSettings.setVisible(toggle);
+ },
+
+ stop: function() {
+ vdebug("Bwhistory@stop");
+ this.saveBandwidth(0,0);
+ },
+};
diff --git a/bwgraph/bwgraph.ui b/bwgraph/bwgraph.ui
new file mode 100644
index 0000000..967ceda
--- /dev/null
+++ b/bwgraph/bwgraph.ui
@@ -0,0 +1,485 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>548</width>
+ <height>499</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="grpBandwidth">
+ <property name="title">
+ <string>Bandwidth history</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="1" colspan="2">
+ <widget class="QLabel" name="lblSent">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="lblSentLabel">
+ <property name="text">
+ <string><b>Data Sent:</b></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="2">
+ <widget class="QLabel" name="lblRecv">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lblFromLabel">
+ <property name="text">
+ <string><b>Since:</b></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="lblSentLabel_2">
+ <property name="text">
+ <string><b>Data Recieved:</b></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QPushButton" name="btnResetHistory">
+ <property name="text">
+ <string>Reset history</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2">
+ <widget class="QLabel" name="lblFrom">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Maximum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>1000</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QFrame" name="frmSettings">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="horizontalSpacing">
+ <number>10</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>5</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="chkReceiveRate">
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>Receive Rate</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="chkSendRate">
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>Send Rate</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="chkAlwaysOnTop">
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>Always on Top</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="3">
+ <widget class="QLabel" name="lblGraphStyle">
+ <property name="text">
+ <string>Style</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <widget class="QComboBox" name="cmbGraphStyle">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../../vidalia/src/vidalia/res/vidalia.qrc">
+ <normaloff>:/images/16x16/graph-line.png</normaloff>:/images/16x16/graph-line.png</iconset>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../../vidalia/src/vidalia/res/vidalia.qrc">
+ <normaloff>:/images/16x16/graph-area.png</normaloff>:/images/16x16/graph-area.png</iconset>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="6">
+ <widget class="QPushButton" name="btnCancelSettings">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="6">
+ <widget class="QPushButton" name="btnSaveSettings">
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" rowspan="2" colspan="4">
+ <widget class="QFrame" name="frmOpacity">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <layout class="QGridLayout" name="gridLayout3">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <item row="0" column="0" colspan="4">
+ <widget class="QSlider" name="sldrOpacity">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="toolTip">
+ <string>Changes the transparency of the Bandwidth Graph</string>
+ </property>
+ <property name="minimum">
+ <number>30</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="sliderPosition">
+ <number>100</number>
+ </property>
+ <property name="tracking">
+ <bool>false</bool>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="invertedAppearance">
+ <bool>false</bool>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::NoTicks</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="lblPercentOpacity">
+ <property name="minimumSize">
+ <size>
+ <width>25</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>100</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label">
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="text">
+ <string>% Opaque</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QFrame" name="graphFrame">
+ <property name="minimumSize">
+ <size>
+ <width>128</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" name="graphLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>10000</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="btnHistory">
+ <property name="text">
+ <string>Show History</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSettings">
+ <property name="text">
+ <string>Show Settings</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnReset">
+ <property name="text">
+ <string>Reset</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>700</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../vidalia/src/vidalia/res/vidalia.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/bwgraph/graphframe.js b/bwgraph/graphframe.js
new file mode 100644
index 0000000..c9e8c14
--- /dev/null
+++ b/bwgraph/graphframe.js
@@ -0,0 +1,297 @@
+importExtension("qt");
+importExtension("qt.core");
+importExtension("qt.gui");
+
+HOR_SPC = 2; /** Space between data points */
+MIN_SCALE = 10; /** 10 kB/s is the minimum scale */
+SCROLL_STEP = 4; /** Horizontal change on graph update */
+
+BACK_COLOR = new QColor(Qt.black);
+SCALE_COLOR = new QColor(Qt.green);
+GRID_COLOR = new QColor(Qt.darkGreen);
+RECV_COLOR = new QColor(Qt.cyan);
+SEND_COLOR = new QColor(Qt.yellow);
+
+FONT_SIZE = 11;
+
+SolidLine = 0;
+AreaGraph = 1;
+
+// TODO: support translations
+function tr(s) { return s; }
+
+function GraphFrame(parent)
+{
+ QFrame.call(this, parent);
+
+ /* Create Graph Frame related objects */
+ this.recvData = [];
+ this.sendData = [];
+ this.painter = new QPainter();
+ this.graphStyle = AreaGraph;
+
+ /* Initialize graph values */
+ this.recvData.unshift(0);
+ this.sendData.unshift(0);
+ this.maxPoints = this.getNumPoints();
+ this.maxPosition = 0;
+ this.showRecv = true;
+ this.showSend = true;
+ this.maxValue = MIN_SCALE;
+ this.scaleWidth = 0;
+ this.totalSend = 0;
+ this.totalRecv = 0;
+}
+
+GraphFrame.prototype = new QFrame();
+
+/** Gets the width of the desktop, which is the maximum number of points
+ * we can plot in the graph. */
+GraphFrame.prototype.getNumPoints = function()
+{
+ return this.size - this.scaleWidth;
+}
+
+/** Adds new data points to the graph. */
+GraphFrame.prototype.addPoints = function(recv, send)
+{
+ /* If maximum number of points plotted, remove oldest */
+ if (this.sendData.length == this.maxPoints) {
+ this.sendData.pop();
+ this.recvData.pop();
+ }
+
+ /* Update the displayed maximum */
+ if (this.maxPosition >= this.maxPoints) {
+ this.maxValue = MIN_SCALE;
+ for(send in this.sendData) {
+ if(send > this.maxValue)
+ this.maxValue = send;
+ }
+ for(recv in this.recvData) {
+ if(recv > this.maxValue)
+ this.maxValue = recv;
+ }
+ this.maxPosition = 0;
+ }
+
+ /* Add the points to their respective lists */
+ this.sendData.unshift(send);
+ this.recvData.unshift(recv);
+
+ /* Add to the total counters */
+ this.totalSend += send;
+ this.totalRecv += recv;
+
+ var maxUpdated = false;
+ /* Check for a new maximum value */
+ if (send > this.maxValue) {
+ this.maxValue = send;
+ maxUpdated = true;
+ }
+
+ if (recv > this.maxValue) {
+ this.maxValue = recv;
+ maxUpdated = true;
+ }
+
+ if (maxUpdated) {
+ this.maxPosition = 0;
+ } else {
+ this.maxPosition++;
+ }
+
+ this.update();
+}
+
+/** Clears the graph. */
+GraphFrame.prototype.resetGraph = function()
+{
+ this.recvData = [];
+ this.sendData = [];
+ this.recvData.unshift(0);
+ this.sendData.unshift(0);
+ this.maxValue = MIN_SCALE;
+ this.totalSend = 0;
+ this.totalRecv = 0;
+ this.update();
+}
+
+/** Toggles display of respective graph lines and counters. */
+GraphFrame.prototype.setShowCounters = function(showRecv, showSend)
+{
+ this.showRecv = showRecv;
+ this.showSend = showSend;
+}
+
+/** Returns a list of points on the bandwidth graph based on the supplied set
+ * of send or receive values. */
+GraphFrame.prototype.pointsFromData = function(list)
+{
+ var points = new Array();
+ var x = this.frameRect.width();
+ var y = this.frameRect.height();
+ var scale = (y - (y/10)) / this.maxValue;
+ var currValue = 0;
+
+ /* Translate all data points to points on the graph frame */
+ points.push(new QPointF(x, y));
+ for (var i = 0; i < list.length; i++) {
+ var item = list[i];
+ currValue = y - (item * scale);
+ if (x - SCROLL_STEP < this.scaleWidth) {
+ points.push(new QPointF(this.scaleWidth, currValue));
+ break;
+ }
+ points.push(new QPointF(x, currValue));
+ x -= SCROLL_STEP;
+ }
+ points.push(new QPointF(this.scaleWidth, y));
+ return points;
+}
+
+/** Returns the width in pixels of <b>label</b> using the current painter's
+ * font. */
+GraphFrame.prototype.labelWidth = function(label)
+{
+ var width = 0;
+ var fm = new QFontMetrics(this.font);
+
+ for (var i = 0; i < label.length; i++)
+ width += fm.charWidth(label, i);
+ return width;
+}
+
+GraphFrame.prototype.resizeEvent = function(ev)
+{
+ this.maxPoints = ev.size().width() - this.scaleWidth;
+ this.maxPoints /= SCROLL_STEP;
+ this.resize(this.parentWidget().size.width(), this.parentWidget().size.height());
+}
+
+GraphFrame.prototype.paintEvent = function(ev)
+{
+ this.painter.begin(this);
+
+ /** Filling */
+ this.painter.setRenderHint(QPainter.Antialiasing);
+ this.painter.setRenderHint(QPainter.TextAntialiasing);
+
+ /* Fill in the background */
+ this.painter.fillRect(this.frameRect, BACK_COLOR);
+
+ /** Paint Scale */
+ var label = new Array();
+ var width = new Array();
+ var top = this.frameRect.y();
+ var bottom = this.frameRect.height();
+ var scaleWidth = 0;
+ var pos = 0;
+ var markStep = this.maxValue * 0.25;
+ var paintStep = (bottom - (bottom/8)) / 4;
+
+ /* Compute each of the y-axis labels */
+ for (var i = 0; i < 4; i++) {
+ pos = bottom - ((i+1) * paintStep);
+ label[i] = (markStep*(i+1)).toFixed(2).toString() + "KB/s";
+ width[i] = this.labelWidth(label[i]);
+ scaleWidth = Math.max(scaleWidth, 2+width[i]);
+ }
+
+ /* Include a 5px margin between the y-axis and its labels */
+ this.scaleWidth = scaleWidth + 5;
+
+ /* Draw the y-axis labels and horizontal marks in their correctly scaled
+ * locations */
+ for (i = 0; i < 4; i++) {
+ pos = bottom - ((i+1) * paintStep);
+ this.painter.setPen(SCALE_COLOR);
+ this.painter.drawText(new QPointF(this.scaleWidth-width[i]-5, pos), String(label[i]));
+
+ this.painter.setPen(GRID_COLOR);
+ this.painter.drawLine(new QPointF(this.scaleWidth, pos),
+ new QPointF(this.frameRect.width(), pos));
+ }
+
+ /* Draw the y-axis */
+ this.painter.drawLine(this.scaleWidth, top, this.scaleWidth, bottom);
+
+ /**********************************************
+ * Paint data *********************************/
+ var recvPoints = [];
+ var sendPoints = [];
+
+ /* Convert the bandwidth data points to graph points */
+ recvPoints = this.pointsFromData(this.recvData);
+ sendPoints = this.pointsFromData(this.sendData);
+
+ if (this.graphStyle == AreaGraph) {
+ /* Plot the bandwidth data as area graphs */
+ if (this.showRecv)
+ {
+ var oldBrush = this.painter.brush();
+ RECV_COLOR.setAlphaF(0.6);
+ this.painter.setBrush(new QBrush(RECV_COLOR));
+ this.painter.drawPolygon(new QPolygonF(recvPoints), Qt.OddEvenFill);
+ this.painter.setBrush(oldBrush);
+ }
+ if (this.showSend)
+ {
+ var oldBrush = this.painter.brush();
+ SEND_COLOR.setAlphaF(0.4);
+ this.painter.setBrush(new QBrush(SEND_COLOR));
+ this.painter.drawPolygon(new QPolygonF(sendPoints), Qt.OddEvenFill);
+ this.painter.setBrush(oldBrush);
+ }
+ }
+
+ /* Plot the bandwidth as solid lines. If the graph style is currently an
+ * area graph, we end up outlining the integrals. */
+ if (this.showRecv)
+ {
+ var oldPen = this.painter.pen();
+ this.painter.setPen(RECV_COLOR);
+ this.painter.drawPolyline(new QPolygonF(recvPoints));
+ this.painter.setPen(oldPen);
+ }
+ if (this.showSend)
+ {
+ var oldPen = this.painter.pen();
+ this.painter.setPen(SEND_COLOR);
+ this.painter.drawPolyline(new QPolygonF(sendPoints));
+ this.painter.setPen(oldPen);
+ }
+
+ /************************************************
+ * Paint totals *********************************/
+ var x = this.scaleWidth + FONT_SIZE;
+ var y = 0;
+ var rowHeight = FONT_SIZE;
+
+ /* On Mac, we don't need vertical spacing between the text rows. */
+ // TODO: see how to use this in this case since we don't have preproc
+ rowHeight += 5;
+
+ /* If total received is selected */
+ if (this.showRecv) {
+ y = rowHeight;
+ this.painter.setPen(RECV_COLOR);
+ var total = Math.floor(this.totalRecv*100) / 100;
+ var count = Math.floor(this.recvData[0]*100) / 100;
+ this.painter.drawText(new QPoint(x, y),
+ tr("Recv:") + " " + total +
+ " (" + count + "KB/s)");
+ }
+
+ /* If total sent is selected */
+ if (this.showSend) {
+ y += rowHeight;
+ this.painter.setPen(SEND_COLOR);
+ var total = Math.floor(this.totalSend*100) / 100;
+ var count = Math.floor(this.sendData[0]*100) / 100;
+ this.painter.drawText(new QPoint(x, y),
+ tr("Sent:") + " " + total +
+ " (" + count + "KB/s)");
+ }
+ this.painter.end();
+}
diff --git a/bwgraph/info.xml b/bwgraph/info.xml
new file mode 100644
index 0000000..7d54654
--- /dev/null
+++ b/bwgraph/info.xml
@@ -0,0 +1,11 @@
+<VidaliaPlugin>
+ <name>Bandwidth Graph</name>
+ <date>11/06/2012</date>
+ <author>chiiph</author>
+ <type persistent="true" gui="true" />
+ <files>
+ <file>graphframe.js</file>
+ <file>bwgraph.js</file>
+ </files>
+ <namespace>bwgraph</namespace>
+</VidaliaPlugin>
1
0
commit 29dccd1f44b895d674079d085207e4e71b43beac
Author: Arturo Filastò <art(a)torproject.org>
Date: Sat Jul 21 01:30:03 2012 +0200
s/b0wser/daphn3/i
because greek mythology is cooler than video games!
---
ooni/plugins/b0wser.py | 100 ----------------
ooni/plugins/daphn3.py | 100 ++++++++++++++++
ooni/protocols/b0wser.py | 284 ----------------------------------------------
ooni/protocols/daphn3.py | 284 ++++++++++++++++++++++++++++++++++++++++++++++
oonib/b0wser.py | 33 ------
oonib/daphn3.py | 33 ++++++
oonib/oonibackend.py | 6 +-
7 files changed, 420 insertions(+), 420 deletions(-)
diff --git a/ooni/plugins/b0wser.py b/ooni/plugins/b0wser.py
deleted file mode 100644
index 3121378..0000000
--- a/ooni/plugins/b0wser.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""
-This is a self genrated test created by scaffolding.py.
-you will need to fill it up with all your necessities.
-Safe hacking :).
-"""
-from zope.interface import implements
-from twisted.python import usage
-from twisted.plugin import IPlugin
-from twisted.internet import protocol, endpoints
-
-from ooni.plugoo.tests import ITest, OONITest
-from ooni.plugoo.assets import Asset
-from ooni.protocols import b0wser
-from ooni.utils import log
-
-class B0wserClientProtocol(b0wser.B0wserProtocol):
- def connectionMade(self):
- self.next_state()
-
- def connectionLost(self, reason):
- print "LOST!"
-
-class B0wserClientFactory(protocol.ClientFactory):
- protocol = B0wserClientProtocol
- mutator = None
- steps = None
-
- def buildProtocol(self, addr):
- p = self.protocol()
- p.factory = self
- if self.steps:
- p.steps = self.steps
-
- if not self.mutator:
- self.mutator = b0wser.Mutator(p.steps)
- p.mutator = self.mutator
- else:
- print "Moving on to next mutation"
- self.mutator.next_mutation()
- return p
-
- def clientConnectionFailed(self, reason):
- print "We failed connecting the the OONIB"
- print "Cannot perform test. Perhaps it got blocked?"
- print "Please report this to tor-assistants(a)torproject.org"
-
- def clientConnectionLost(self, reason):
- print "Connection Lost."
-
-class b0wserArgs(usage.Options):
- optParameters = [['pcap', 'f', None, 'PCAP file to take as input'],
- ['host', 'h', None, 'Target Hostname'],
- ['port', 'p', None, 'Target port number'],
- ['resume', 'r', 0, 'Resume at this index']]
-
-class b0wserTest(OONITest):
- implements(IPlugin, ITest)
-
- shortName = "b0wser"
- description = "b0wser"
- requirements = None
- options = b0wserArgs
- blocking = False
-
- local_options = None
-
- steps = None
- def initialize(self):
- if not self.local_options:
- return
- #pass
- self.factory = B0wserClientFactory()
- self.steps = b0wser.get_b0wser_dictionary_from_pcap(self.local_options['pcap'])
-
- def control(self, exp_res, args):
- mutation = self.factory.mutator.get_mutation(0)
- return {'mutation_number': args['mutation'], 'value': mutation}
-
- def experiment(self, args):
- log.msg("Doing mutation %s" % args['mutation'])
- self.factory.steps = self.steps
- host = self.local_options['host']
- port = int(self.local_options['port'])
- log.msg("Connecting to %s:%s" % (host, port))
- endpoint = endpoints.TCP4ClientEndpoint(self.reactor, host, port)
- return endpoint.connect(self.factory)
- #return endpoint.connect(B0wserClientFactory)
-
- def load_assets(self):
- if not self.steps:
- print "No asset!"
- return {}
- mutations = 0
- for x in self.steps:
- mutations += len(x['data'])
- return {'mutation': range(mutations)}
-
-# We need to instantiate it otherwise getPlugins does not detect it
-# XXX Find a way to load plugins without instantiating them.
-b0wsertest = b0wserTest(None, None, None)
diff --git a/ooni/plugins/daphn3.py b/ooni/plugins/daphn3.py
new file mode 100644
index 0000000..6dd9da2
--- /dev/null
+++ b/ooni/plugins/daphn3.py
@@ -0,0 +1,100 @@
+"""
+This is a self genrated test created by scaffolding.py.
+you will need to fill it up with all your necessities.
+Safe hacking :).
+"""
+from zope.interface import implements
+from twisted.python import usage
+from twisted.plugin import IPlugin
+from twisted.internet import protocol, endpoints
+
+from ooni.plugoo.tests import ITest, OONITest
+from ooni.plugoo.assets import Asset
+from ooni.protocols import daphn3
+from ooni.utils import log
+
+class Daphn3ClientProtocol(daphn3.Daphn3Protocol):
+ def connectionMade(self):
+ self.next_state()
+
+ def connectionLost(self, reason):
+ print "LOST!"
+
+class Daphn3ClientFactory(protocol.ClientFactory):
+ protocol = Daphn3ClientProtocol
+ mutator = None
+ steps = None
+
+ def buildProtocol(self, addr):
+ p = self.protocol()
+ p.factory = self
+ if self.steps:
+ p.steps = self.steps
+
+ if not self.mutator:
+ self.mutator = daphn3.Mutator(p.steps)
+ p.mutator = self.mutator
+ else:
+ print "Moving on to next mutation"
+ self.mutator.next_mutation()
+ return p
+
+ def clientConnectionFailed(self, reason):
+ print "We failed connecting the the OONIB"
+ print "Cannot perform test. Perhaps it got blocked?"
+ print "Please report this to tor-assistants(a)torproject.org"
+
+ def clientConnectionLost(self, reason):
+ print "Connection Lost."
+
+class daphn3Args(usage.Options):
+ optParameters = [['pcap', 'f', None, 'PCAP file to take as input'],
+ ['host', 'h', None, 'Target Hostname'],
+ ['port', 'p', None, 'Target port number'],
+ ['resume', 'r', 0, 'Resume at this index']]
+
+class daphn3Test(OONITest):
+ implements(IPlugin, ITest)
+
+ shortName = "daphn3"
+ description = "daphn3"
+ requirements = None
+ options = daphn3Args
+ blocking = False
+
+ local_options = None
+
+ steps = None
+ def initialize(self):
+ if not self.local_options:
+ return
+ #pass
+ self.factory = Daphn3ClientFactory()
+ self.steps = daphn3.get_daphn3_dictionary_from_pcap(self.local_options['pcap'])
+
+ def control(self, exp_res, args):
+ mutation = self.factory.mutator.get_mutation(0)
+ return {'mutation_number': args['mutation'], 'value': mutation}
+
+ def experiment(self, args):
+ log.msg("Doing mutation %s" % args['mutation'])
+ self.factory.steps = self.steps
+ host = self.local_options['host']
+ port = int(self.local_options['port'])
+ log.msg("Connecting to %s:%s" % (host, port))
+ endpoint = endpoints.TCP4ClientEndpoint(self.reactor, host, port)
+ return endpoint.connect(self.factory)
+ #return endpoint.connect(Daphn3ClientFactory)
+
+ def load_assets(self):
+ if not self.steps:
+ print "No asset!"
+ return {}
+ mutations = 0
+ for x in self.steps:
+ mutations += len(x['data'])
+ return {'mutation': range(mutations)}
+
+# We need to instantiate it otherwise getPlugins does not detect it
+# XXX Find a way to load plugins without instantiating them.
+daphn3test = daphn3Test(None, None, None)
diff --git a/ooni/protocols/b0wser.py b/ooni/protocols/b0wser.py
deleted file mode 100644
index 5d55c94..0000000
--- a/ooni/protocols/b0wser.py
+++ /dev/null
@@ -1,284 +0,0 @@
-from twisted.internet import protocol, defer
-from twisted.internet.error import ConnectionDone
-
-from ooni.utils import log
-from ooni.plugoo import reports
-
-import sys
-from scapy.all import *
-import yaml
-
-def get_b0wser_dictionary_from_pcap(filename):
- """
- @param filename: Filesystem path to the pcap.
-
- Returns:
- [{"sender": "client", "data": "\x17\x52\x15"}, {"sender": "server", "data": "\x17\x15\x13"}]
- """
- packets = rdpcap(filename)
-
- checking_first_packet = True
- client_ip_addr = None
- server_ip_addr = None
-
- ssl_packets = []
- messages = []
-
- """
- pcap assumptions:
-
- pcap only contains packets exchanged between a Tor client and a Tor server.
- (This assumption makes sure that there are only two IP addresses in the
- pcap file)
-
- The first packet of the pcap is sent from the client to the server. (This
- assumption is used to get the IP address of the client.)
-
- All captured packets are TLS packets: that is TCP session
- establishment/teardown packets should be filtered out (no SYN/SYN+ACK)
- """
-
- """Minimally validate the pcap and also find out what's the client
- and server IP addresses."""
- for packet in packets:
- if checking_first_packet:
- client_ip_addr = packet[IP].src
- checking_first_packet = False
- else:
- if packet[IP].src != client_ip_addr:
- server_ip_addr = packet[IP].src
-
- try:
- if (packet[Raw]):
- ssl_packets.append(packet)
- except IndexError:
- pass
-
- """Form our list."""
- for packet in ssl_packets:
- if packet[IP].src == client_ip_addr:
- messages.append({"sender": "client", "data": str(packet[Raw])})
- elif packet[IP].src == server_ip_addr:
- messages.append({"sender": "server", "data": str(packet[Raw])})
- else:
- raise("Detected third IP address! pcap is corrupted.")
-
- return messages
-
-class Mutator:
- idx = 0
- step = 0
-
- waiting = False
- waiting_step = 0
-
- def __init__(self, steps):
- """
- @param steps: array of dicts containing as keys data and wait. Data is
- the content of the ith packet to be sent and wait is how
- much we should wait before mutating the packet of the
- next step.
- """
- self.steps = steps
-
- def _mutate(self, data, idx):
- """
- Mutate the idx bytes by increasing it's value by one
-
- @param data: the data to be mutated.
-
- @param idx: what byte should be mutated.
- """
- print "idx: %s, data: %s" % (idx, data)
- ret = data[:idx]
- ret += chr(ord(data[idx]) + 1)
- ret += data[idx+1:]
- return ret
-
- def state(self):
- """
- Return the current mutation state. As in what bytes are being mutated.
-
- Returns a dict containg the packet index and the step number.
- """
- print "[Mutator.state()] Giving out my internal state."
- current_state = {'idx': self.idx, 'step': self.step}
- return current_state
-
- def next_mutation(self):
- """
- Increases by one the mutation state.
-
- ex. (* is the mutation state, i.e. the byte to be mutated)
- before [___*] [____]
- step1 step2
- after [____] [*___]
-
- Should be called every time you need to proceed onto the next mutation.
- It changes the internal state of the mutator to that of the next
- mutatation.
-
- returns True if another mutation is available.
- returns False if all the possible mutations have been done.
- """
- if (self.step + 1) > len(self.steps):
- # Hack to stop once we have gone through all the steps
- print "[Mutator.next_mutation()] I believe I have gone over all steps"
- print " Stopping!"
- self.waiting = True
- return False
-
- self.idx += 1
- current_idx = self.idx
- current_step = self.step
- current_data = self.steps[current_step]['data']
- try:
- data_to_receive = len(self.steps[current_step +1 ]['data'])
- print "[Mutator.next_mutation()] Managed to receive some data."
- except:
- print "[Mutator.next_mutation()] No more data to receive."
-
- if self.waiting and self.waiting_step == data_to_receive:
- print "[Mutator.next_mutation()] I am no longer waiting"
- log.debug("I am no longer waiting.")
- self.waiting = False
- self.waiting_step = 0
- self.idx = 0
-
- elif self.waiting:
- print "[Mutator.next_mutation()] Waiting some more."
- log.debug("Waiting some more.")
- self.waiting_step += 1
-
- elif current_idx >= len(current_data):
- print "[Mutator.next_mutation()] Entering waiting mode."
- log.debug("Entering waiting mode.")
- self.step += 1
- self.idx = 0
- self.waiting = True
- log.debug("current index %s" % current_idx)
- log.debug("current data %s" % len(current_data))
- return True
-
- def get_mutation(self, step):
- """
- Returns the current packet to be sent to the wire.
- If no mutation is necessary it will return the plain data.
- Should be called when you are interested in obtaining the data to be
- sent for the selected state.
-
- @param step: the current step you want the mutation for
-
- returns the mutated packet for the specified step.
- """
- if step != self.step or self.waiting:
- log.debug("[Mutator.get_mutation()] I am not going to do anything :)")
- return self.steps[step]['data']
-
- data = self.steps[step]['data']
- print "Mutating %s with idx %s" % (data, self.idx)
- return self._mutate(data, self.idx)
-
-class B0wserProtocol(protocol.Protocol):
- """
- This implements the B0wser protocol for the server side.
- It gets instanced once for every client that connects to the oonib.
- For every instance of protocol there is only 1 mutation.
- Once the last step is reached the connection is closed on the serverside.
- """
- steps = []
- mutator = None
-
- role = 'client'
- state = 0
- total_states = len(steps) - 1
- received_data = 0
- to_receive_data = 0
- report = reports.Report('b0wser', 'b0wser.yamlooni')
-
- def next_state(self):
- """
- This is called once I have completed one step of the protocol and need
- to proceed to the next step.
- """
- if not self.mutator:
- print "[B0wserProtocol.next_state] No mutator. There is no point to stay on this earth."
- self.transport.loseConnection()
- return
- if self.role is self.steps[self.state]['sender']:
- print "[B0wserProtocol.next_state] I am a sender"
- data = self.mutator.get_mutation(self.state)
- self.transport.write(data)
- self.to_receive_data = 0
- else:
- print "[B0wserProtocol.next_state] I am a receiver"
- self.to_receive_data = len(self.steps[self.state]['data'])
-
- self.state += 1
- self.received_data = 0
-
- def dataReceived(self, data):
- """
- This is called every time some data is received. I transition to the
- next step once the amount of data that I expect to receive is received.
-
- @param data: the data that has been sent by the client.
- """
- if not self.mutator:
- print "I don't have a mutator. My life means nothing."
- self.transport.loseConnection()
- return
- if len(self.steps) <= self.state:
- print "I have reached the end of the state machine"
- print "Censorship fingerprint bruteforced!"
- report = {'mutator_state': self.mutator.state()}
- self.report(report)
- self.transport.loseConnection()
- return
-
- self.received_data += len(data)
- if self.received_data >= self.to_receive_data:
- print "Moving to next state %s" % self.state
- self.next_state()
-
- def censorship_detected(self, report):
- """
- I have detected the possible presence of censorship we need to write a
- report on it.
-
- @param report: a dict containing the report to be written. Must contain
- the keys 'reason', 'proto_state' and 'mutator_state'.
- The reason is the reason for which the connection was
- closed. The proto_state is the current state of the
- protocol instance and mutator_state is what was being
- mutated.
- """
- print "The connection was closed because of %s" % report['reason']
- print "State %s, Mutator %s" % (report['proto_state'],
- report['mutator_state'])
- self.mutator.next_mutation()
-
-
-
- def connectionLost(self, reason):
- """
- The connection was closed. This may be because of a legittimate reason
- or it may be because of a censorship event.
- """
- if not self.mutator:
- print "Terminated because of little interest in life."
- return
- report = {'reason': reason, 'proto_state': self.state,
- 'trigger': None, 'mutator_state': self.mutator.state()}
-
- if self.state < self.total_states:
- report['trigger'] = 'did not finish state walk'
- self.censorship_detected(report)
-
- if reason.check(ConnectionDone):
- print "Connection closed cleanly"
- else:
- report['trigger'] = 'unclean connection closure'
- self.censorship_detected(report)
-
-
diff --git a/ooni/protocols/daphn3.py b/ooni/protocols/daphn3.py
new file mode 100644
index 0000000..d8290e6
--- /dev/null
+++ b/ooni/protocols/daphn3.py
@@ -0,0 +1,284 @@
+from twisted.internet import protocol, defer
+from twisted.internet.error import ConnectionDone
+
+from ooni.utils import log
+from ooni.plugoo import reports
+
+import sys
+from scapy.all import *
+import yaml
+
+def get_daphn3_dictionary_from_pcap(filename):
+ """
+ @param filename: Filesystem path to the pcap.
+
+ Returns:
+ [{"sender": "client", "data": "\x17\x52\x15"}, {"sender": "server", "data": "\x17\x15\x13"}]
+ """
+ packets = rdpcap(filename)
+
+ checking_first_packet = True
+ client_ip_addr = None
+ server_ip_addr = None
+
+ ssl_packets = []
+ messages = []
+
+ """
+ pcap assumptions:
+
+ pcap only contains packets exchanged between a Tor client and a Tor server.
+ (This assumption makes sure that there are only two IP addresses in the
+ pcap file)
+
+ The first packet of the pcap is sent from the client to the server. (This
+ assumption is used to get the IP address of the client.)
+
+ All captured packets are TLS packets: that is TCP session
+ establishment/teardown packets should be filtered out (no SYN/SYN+ACK)
+ """
+
+ """Minimally validate the pcap and also find out what's the client
+ and server IP addresses."""
+ for packet in packets:
+ if checking_first_packet:
+ client_ip_addr = packet[IP].src
+ checking_first_packet = False
+ else:
+ if packet[IP].src != client_ip_addr:
+ server_ip_addr = packet[IP].src
+
+ try:
+ if (packet[Raw]):
+ ssl_packets.append(packet)
+ except IndexError:
+ pass
+
+ """Form our list."""
+ for packet in ssl_packets:
+ if packet[IP].src == client_ip_addr:
+ messages.append({"sender": "client", "data": str(packet[Raw])})
+ elif packet[IP].src == server_ip_addr:
+ messages.append({"sender": "server", "data": str(packet[Raw])})
+ else:
+ raise("Detected third IP address! pcap is corrupted.")
+
+ return messages
+
+class Mutator:
+ idx = 0
+ step = 0
+
+ waiting = False
+ waiting_step = 0
+
+ def __init__(self, steps):
+ """
+ @param steps: array of dicts containing as keys data and wait. Data is
+ the content of the ith packet to be sent and wait is how
+ much we should wait before mutating the packet of the
+ next step.
+ """
+ self.steps = steps
+
+ def _mutate(self, data, idx):
+ """
+ Mutate the idx bytes by increasing it's value by one
+
+ @param data: the data to be mutated.
+
+ @param idx: what byte should be mutated.
+ """
+ print "idx: %s, data: %s" % (idx, data)
+ ret = data[:idx]
+ ret += chr(ord(data[idx]) + 1)
+ ret += data[idx+1:]
+ return ret
+
+ def state(self):
+ """
+ Return the current mutation state. As in what bytes are being mutated.
+
+ Returns a dict containg the packet index and the step number.
+ """
+ print "[Mutator.state()] Giving out my internal state."
+ current_state = {'idx': self.idx, 'step': self.step}
+ return current_state
+
+ def next_mutation(self):
+ """
+ Increases by one the mutation state.
+
+ ex. (* is the mutation state, i.e. the byte to be mutated)
+ before [___*] [____]
+ step1 step2
+ after [____] [*___]
+
+ Should be called every time you need to proceed onto the next mutation.
+ It changes the internal state of the mutator to that of the next
+ mutatation.
+
+ returns True if another mutation is available.
+ returns False if all the possible mutations have been done.
+ """
+ if (self.step + 1) > len(self.steps):
+ # Hack to stop once we have gone through all the steps
+ print "[Mutator.next_mutation()] I believe I have gone over all steps"
+ print " Stopping!"
+ self.waiting = True
+ return False
+
+ self.idx += 1
+ current_idx = self.idx
+ current_step = self.step
+ current_data = self.steps[current_step]['data']
+ try:
+ data_to_receive = len(self.steps[current_step +1 ]['data'])
+ print "[Mutator.next_mutation()] Managed to receive some data."
+ except:
+ print "[Mutator.next_mutation()] No more data to receive."
+
+ if self.waiting and self.waiting_step == data_to_receive:
+ print "[Mutator.next_mutation()] I am no longer waiting"
+ log.debug("I am no longer waiting.")
+ self.waiting = False
+ self.waiting_step = 0
+ self.idx = 0
+
+ elif self.waiting:
+ print "[Mutator.next_mutation()] Waiting some more."
+ log.debug("Waiting some more.")
+ self.waiting_step += 1
+
+ elif current_idx >= len(current_data):
+ print "[Mutator.next_mutation()] Entering waiting mode."
+ log.debug("Entering waiting mode.")
+ self.step += 1
+ self.idx = 0
+ self.waiting = True
+ log.debug("current index %s" % current_idx)
+ log.debug("current data %s" % len(current_data))
+ return True
+
+ def get_mutation(self, step):
+ """
+ Returns the current packet to be sent to the wire.
+ If no mutation is necessary it will return the plain data.
+ Should be called when you are interested in obtaining the data to be
+ sent for the selected state.
+
+ @param step: the current step you want the mutation for
+
+ returns the mutated packet for the specified step.
+ """
+ if step != self.step or self.waiting:
+ log.debug("[Mutator.get_mutation()] I am not going to do anything :)")
+ return self.steps[step]['data']
+
+ data = self.steps[step]['data']
+ print "Mutating %s with idx %s" % (data, self.idx)
+ return self._mutate(data, self.idx)
+
+class Daphn3Protocol(protocol.Protocol):
+ """
+ This implements the Daphn3 protocol for the server side.
+ It gets instanced once for every client that connects to the oonib.
+ For every instance of protocol there is only 1 mutation.
+ Once the last step is reached the connection is closed on the serverside.
+ """
+ steps = []
+ mutator = None
+
+ role = 'client'
+ state = 0
+ total_states = len(steps) - 1
+ received_data = 0
+ to_receive_data = 0
+ report = reports.Report('daphn3', 'daphn3.yamlooni')
+
+ def next_state(self):
+ """
+ This is called once I have completed one step of the protocol and need
+ to proceed to the next step.
+ """
+ if not self.mutator:
+ print "[Daphn3Protocol.next_state] No mutator. There is no point to stay on this earth."
+ self.transport.loseConnection()
+ return
+ if self.role is self.steps[self.state]['sender']:
+ print "[Daphn3Protocol.next_state] I am a sender"
+ data = self.mutator.get_mutation(self.state)
+ self.transport.write(data)
+ self.to_receive_data = 0
+ else:
+ print "[Daphn3Protocol.next_state] I am a receiver"
+ self.to_receive_data = len(self.steps[self.state]['data'])
+
+ self.state += 1
+ self.received_data = 0
+
+ def dataReceived(self, data):
+ """
+ This is called every time some data is received. I transition to the
+ next step once the amount of data that I expect to receive is received.
+
+ @param data: the data that has been sent by the client.
+ """
+ if not self.mutator:
+ print "I don't have a mutator. My life means nothing."
+ self.transport.loseConnection()
+ return
+ if len(self.steps) <= self.state:
+ print "I have reached the end of the state machine"
+ print "Censorship fingerprint bruteforced!"
+ report = {'mutator_state': self.mutator.state()}
+ self.report(report)
+ self.transport.loseConnection()
+ return
+
+ self.received_data += len(data)
+ if self.received_data >= self.to_receive_data:
+ print "Moving to next state %s" % self.state
+ self.next_state()
+
+ def censorship_detected(self, report):
+ """
+ I have detected the possible presence of censorship we need to write a
+ report on it.
+
+ @param report: a dict containing the report to be written. Must contain
+ the keys 'reason', 'proto_state' and 'mutator_state'.
+ The reason is the reason for which the connection was
+ closed. The proto_state is the current state of the
+ protocol instance and mutator_state is what was being
+ mutated.
+ """
+ print "The connection was closed because of %s" % report['reason']
+ print "State %s, Mutator %s" % (report['proto_state'],
+ report['mutator_state'])
+ self.mutator.next_mutation()
+
+
+
+ def connectionLost(self, reason):
+ """
+ The connection was closed. This may be because of a legittimate reason
+ or it may be because of a censorship event.
+ """
+ if not self.mutator:
+ print "Terminated because of little interest in life."
+ return
+ report = {'reason': reason, 'proto_state': self.state,
+ 'trigger': None, 'mutator_state': self.mutator.state()}
+
+ if self.state < self.total_states:
+ report['trigger'] = 'did not finish state walk'
+ self.censorship_detected(report)
+
+ if reason.check(ConnectionDone):
+ print "Connection closed cleanly"
+ else:
+ report['trigger'] = 'unclean connection closure'
+ self.censorship_detected(report)
+
+
diff --git a/oonib/b0wser.py b/oonib/b0wser.py
deleted file mode 100644
index 4500075..0000000
--- a/oonib/b0wser.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from twisted.internet import protocol
-from twisted.internet.error import ConnectionDone
-
-from ooni.plugoo import reports
-from ooni.protocols.b0wser import Mutator, B0wserProtocol
-
-class B0wserServer(protocol.ServerFactory):
- """
- This is the main class that deals with the b0wser server side component.
- We keep track of global state of every client here.
- Every client is identified by their IP address and the state of mutation is
- stored by using their IP address as a key. This may lead to some bugs if
- two different clients are sharing the same IP, but hopefully the
- probability of such thing is not that likely.
- """
- protocol = B0wserProtocol
- mutations = {}
- def buildProtocol(self, addr):
- p = self.protocol()
- p.factory = self
-
- if addr.host not in self.mutations:
- self.mutations[addr.host] = Mutator(p.steps)
- else:
- print "Moving on to next mutation"
- if not self.mutations[addr.host].next_mutation():
- self.mutations.pop(addr.host)
- try:
- p.mutator = self.mutations[addr.host]
- except:
- pass
- return p
-
diff --git a/oonib/daphn3.py b/oonib/daphn3.py
new file mode 100644
index 0000000..22aef49
--- /dev/null
+++ b/oonib/daphn3.py
@@ -0,0 +1,33 @@
+from twisted.internet import protocol
+from twisted.internet.error import ConnectionDone
+
+from ooni.plugoo import reports
+from ooni.protocols.daphn3 import Mutator, daphn3Protocol
+
+class daphn3Server(protocol.ServerFactory):
+ """
+ This is the main class that deals with the daphn3 server side component.
+ We keep track of global state of every client here.
+ Every client is identified by their IP address and the state of mutation is
+ stored by using their IP address as a key. This may lead to some bugs if
+ two different clients are sharing the same IP, but hopefully the
+ probability of such thing is not that likely.
+ """
+ protocol = daphn3Protocol
+ mutations = {}
+ def buildProtocol(self, addr):
+ p = self.protocol()
+ p.factory = self
+
+ if addr.host not in self.mutations:
+ self.mutations[addr.host] = Mutator(p.steps)
+ else:
+ print "Moving on to next mutation"
+ if not self.mutations[addr.host].next_mutation():
+ self.mutations.pop(addr.host)
+ try:
+ p.mutator = self.mutations[addr.host]
+ except:
+ pass
+ return p
+
diff --git a/oonib/oonibackend.py b/oonib/oonibackend.py
index 4ae275e..22a8728 100755
--- a/oonib/oonibackend.py
+++ b/oonib/oonibackend.py
@@ -18,7 +18,7 @@ from twisted.names import dns
from oonib.httpbackend import HTTPBackend
from oonib.dnsbackend import ProxyDNSServer
-from oonib.b0wser import B0wserServer
+from oonib.daphn3 import Daphn3Server
# This tells twisted to set the
server.version = "Apache"
@@ -34,5 +34,5 @@ UDPFactory = dns.DNSDatagramProtocol(TCPDNSServer)
internet.UDPServer(5354, UDPFactory).setServiceParent(serviceCollection)
# Start the ooni backend thing
-b0wser = B0wserServer()
-internet.TCPServer(9666, b0wser).setServiceParent(serviceCollection)
+daphn3 = Daphn3Server()
+internet.TCPServer(9666, daphn3).setServiceParent(serviceCollection)
1
0
[stegotorus/master] More size_t values must be cast to unsigned long
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 4195993aa3e15ebfc895299d5b8342971067ec12
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Thu May 3 10:40:21 2012 -0700
More size_t values must be cast to unsigned long
---
src/network.cc | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/network.cc b/src/network.cc
index 6039df0..f436ef4 100644
--- a/src/network.cc
+++ b/src/network.cc
@@ -378,10 +378,10 @@ downstream_event_cb(struct bufferevent *bev, short what, void *arg)
{
conn_t *conn = (conn_t *)arg;
- log_debug(conn, "what=%04hx enabled=%x inbound=%ld outbound=%ld",
+ log_debug(conn, "what=%04hx enabled=%x inbound=%lu outbound=%lu",
what, bufferevent_get_enabled(bev),
- evbuffer_get_length(bufferevent_get_input(bev)),
- evbuffer_get_length(bufferevent_get_output(bev)));
+ (unsigned long)evbuffer_get_length(bufferevent_get_input(bev)),
+ (unsigned long)evbuffer_get_length(bufferevent_get_output(bev)));
if (what & (BEV_EVENT_ERROR|BEV_EVENT_EOF|BEV_EVENT_TIMEOUT)) {
if (what & BEV_EVENT_ERROR)
1
0