tor-commits
Threads by month
- ----- 2025 -----
- 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
- 213390 discussions

10 Jun '11
commit 155c58fe5ddb1734b4b5a46b0a7906cbf01677d5
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Jun 10 08:36:54 2011 -0700
Adding source flag to disable gui while in beta
Source flag disables the --gui argument (and by extention prevents the gui
from being run). This isn't perfect in that the gui prereqs are checked
despite this flag when we have the gui arg, but this is both a temporary hack
and not a terribly big concern.
---
src/starter.py | 17 …
[View More]++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/starter.py b/src/starter.py
index edb8bb2..d2ac910 100644
--- a/src/starter.py
+++ b/src/starter.py
@@ -30,6 +30,7 @@ import util.uiTools
import TorCtl.TorCtl
import TorCtl.TorUtil
+INCLUDE_GUI = False
LOG_DUMP_PATH = os.path.expanduser("~/.arm/log")
DEFAULT_CONFIG = os.path.expanduser("~/.arm/armrc")
CONFIG = {"startup.controlPassword": None,
@@ -50,8 +51,13 @@ CONFIG = {"startup.controlPassword": None,
"log.configDescriptions.persistance.saveFailed": util.log.NOTICE,
"log.savingDebugLog": util.log.NOTICE}
-OPT = "gi:c:dbe:vh"
-OPT_EXPANDED = ["gui", "interface=", "config=", "debug", "blind", "event=", "version", "help"]
+if INCLUDE_GUI:
+ OPT = "gi:c:dbe:vh"
+ OPT_EXPANDED = ["gui", "interface=", "config=", "debug", "blind", "event=", "version", "help"]
+else:
+ OPT = "i:c:dbe:vh"
+ OPT_EXPANDED = ["interface=", "config=", "debug", "blind", "event=", "version", "help"]
+
HELP_MSG = """Usage arm [OPTION]
Terminal status monitor for Tor relays.
@@ -71,6 +77,11 @@ arm -b -i 1643 hide connection data, attaching to control port 1643
arm -e we -c /tmp/cfg use this configuration file with 'WARN'/'ERR' events
""" % (CONFIG["startup.interface.ipAddress"], CONFIG["startup.interface.port"], DEFAULT_CONFIG, LOG_DUMP_PATH, CONFIG["startup.events"], cli.logPanel.EVENT_LISTING)
+# icky and temporary hack to remove the gui help option if it's unavailbe
+if not INCLUDE_GUI:
+ helpComp = HELP_MSG.split("\n")
+ HELP_MSG = "\n".join(helpComp[:3] + helpComp[4:])
+
# filename used for cached tor config descriptions
CONFIG_DESC_FILENAME = "torConfigDesc.txt"
@@ -239,7 +250,7 @@ if __name__ == '__main__':
param["startup.interface.ipAddress"] = controlAddr
param["startup.interface.port"] = controlPort
- elif opt in ("-g", "--gui"): launchGui = True
+ elif opt in ("-g", "--gui") and INCLUDE_GUI: launchGui = True
elif opt in ("-c", "--config"): configPath = arg # sets path of user's config
elif opt in ("-d", "--debug"): isDebugMode = True # dumps all logs
elif opt in ("-b", "--blind"):
[View Less]
1
0
commit d4a7db902d187810b3ce2b3ba247dbd2760eeeef
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Sun Jun 5 21:13:49 2011 +0500
Fixed file mode.
---
0 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/src/gui/controller.py b/src/gui/controller.py
old mode 100755
new mode 100644
1
0
commit 5ed6caafc77f43a389c7fcafa829803983c490a5
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Sun Jun 5 21:10:48 2011 +0500
Skeletal Gtk+ UI.
Launched via -g or --gtk command-line flag. Rudimentary usage of
torTools to display Tor pid.
---
src/gui/__init__.py | 6 +
src/gui/arm.xml | 628 +++++++++++++++++++++++++++++++++++++++++++++++++
src/gui/controller.py | 85 +++++++
src/starter.py | 13 +-
4 files changed, 729 insertions(+), 3 …
[View More]deletions(-)
diff --git a/src/gui/__init__.py b/src/gui/__init__.py
new file mode 100644
index 0000000..f461b3e
--- /dev/null
+++ b/src/gui/__init__.py
@@ -0,0 +1,6 @@
+"""
+Panels, popups, and handlers comprising the arm user interface.
+"""
+
+__all__ = ["controller"]
+
diff --git a/src/gui/arm.xml b/src/gui/arm.xml
new file mode 100644
index 0000000..49ffc89
--- /dev/null
+++ b/src/gui/arm.xml
@@ -0,0 +1,628 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkListStore" id="liststore_sticky">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray2 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray3 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray4 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">arm</col>
+ <col id="1" translatable="yes">orthanc (Linux 2.6.35.11-83.fc14)</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Tor</col>
+ <col id="1" translatable="yes">0.2.1.28 (obsolete)</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">black</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Relaying</col>
+ <col id="1" translatable="yes">Disabled</col>
+ <col id="2" translatable="yes">red</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Control Port</col>
+ <col id="1" translatable="yes">9051 (open)</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">CPU Tor</col>
+ <col id="1" translatable="yes">0.0%</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">CPU arm</col>
+ <col id="1" translatable="yes">0.0%</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Memory</col>
+ <col id="1" translatable="yes">20 MB (1.0%)</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">PID</col>
+ <col id="1" translatable="yes">3980</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Uptime</col>
+ <col id="1" translatable="yes">01:01:34</col>
+ <col id="2" translatable="yes">black</col>
+ <col id="3" translatable="yes">white</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="liststore_conn">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray2 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray3 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray4 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray5 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray6 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">115.167.31.237:56835</col>
+ <col id="1" translatable="yes">188.120.245.249:9001 (ru)</col>
+ <col id="2" translatable="yes">10.7m</col>
+ <col id="3" translatable="yes">CLIENT</col>
+ <col id="4" translatable="yes">blue</col>
+ <col id="5" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">115.167.31.237:44940</col>
+ <col id="1" translatable="yes">206.217.215.183:53 (us)</col>
+ <col id="2" translatable="yes">28.3m</col>
+ <col id="3" translatable="yes">CLIENT</col>
+ <col id="4" translatable="yes">blue</col>
+ <col id="5" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">127.0.0.1:9051</col>
+ <col id="1" translatable="yes">127.0.0.1:51665</col>
+ <col id="2" translatable="yes">30.0m</col>
+ <col id="3" translatable="yes">CONTROL</col>
+ <col id="4" translatable="yes">red</col>
+ <col id="5" translatable="yes">white</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="liststore_config">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray2 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray3 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray4 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray5 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">BandwidthRate</col>
+ <col id="1" translatable="yes">5242880</col>
+ <col id="2" translatable="yes">Average bandwidth usage limit</col>
+ <col id="3" translatable="yes">#368918</col>
+ <col id="4" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">BandwidthBurst</col>
+ <col id="1" translatable="yes">10485760</col>
+ <col id="2" translatable="yes">Maximum bandwidth usage limit</col>
+ <col id="3" translatable="yes">#368918</col>
+ <col id="4" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">RelayBandwidthBurst</col>
+ <col id="1" translatable="yes">0 B</col>
+ <col id="2" translatable="yes">Maximum bandwidth usage limit for relaying</col>
+ <col id="3" translatable="yes">#368918</col>
+ <col id="4" translatable="yes">white</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">ControlPort</col>
+ <col id="1" translatable="yes">9051</col>
+ <col id="2" translatable="yes">Port providing access to tor controllers (arm, vidalia, etc)</col>
+ <col id="3" translatable="yes">#368918</col>
+ <col id="4" translatable="yes">white</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkWindow" id="window_main">
+ <property name="title" translatable="yes">arm</property>
+ <property name="default_width">640</property>
+ <property name="default_height">480</property>
+ <signal name="delete_event" handler="on_window_main_delete_event"/>
+ <child>
+ <object class="GtkVBox" id="vbox_main">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar_main">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_file">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu_file">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_new">
+ <property name="label">gtk-new</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_open">
+ <property name="label">gtk-open</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_save">
+ <property name="label">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_saveas">
+ <property name="label">gtk-save-as</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="separatormenuitem_file">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_exit">
+ <property name="label">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_edit">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu_edit">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_cut">
+ <property name="label">gtk-cut</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_copy">
+ <property name="label">gtk-copy</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_paste">
+ <property name="label">gtk-paste</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_delete">
+ <property name="label">gtk-delete</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_view">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_help">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu_help">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_about">
+ <property name="label">gtk-about</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_main">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkNotebook" id="notebook_main">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox_graph">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_graph_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Limit: 40 Mb/s, Burst: 80 Mb/s</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_graph">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox_graph_a">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_graph_a_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Download (0.0 b/sec)</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCurve" id="curve_graph_a">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_graph_a_bottom">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">avg: 3.5 Kb/sec, total: 2.0 MB</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_graph_b">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_graph_b_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Upload (0.0 b/sec)</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCurve" id="curve_graph_b">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_graph_b_bottom">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">avg: 3.5 Kb/sec, total: 2.0 MB</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_graph">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Graphs</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_conn">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_conn_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">2 Clients, 1 Control</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTreeView" id="treeview_conn">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">liststore_conn</property>
+ <property name="headers_visible">False</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_origin">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_dest">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_time">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_alive">
+ <property name="title">column</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_conn">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Connections</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_config">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_config_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><span foreground="#368918"><u>RelayBandwidthBurst</u> (General Option)
+<b>Value</b>: 0 B (default, DataSize, usage: N bytes|KB|MB|GB|TB)
+<b>Description</b>: Limit the maximum token bucket size (also known as
+the burst) for <i>relayed traffic</i> to the given number of bytes in
+each direction. (Default: 0) </span></property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_config">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_config">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">liststore_config</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_name">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_value">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_desc">
+ <property name="title">column</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_config">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Configuration</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_sticky">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_sticky">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">liststore_sticky</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_name">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_value">
+ <property name="title">column</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_log">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTextView" id="textview_log">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkTextBuffer" id="textbuffer_log">
+ <property name="text" translatable="yes">16:09:20 [NOTICE] Bootstrapped 90%: Establishing a Tor circuit.
+16:09:23 [NOTICE] Tor has successfully opened a circuit. Looks like client functionality is working.
+16:09:23 [NOTICE] Tor has successfully opened a circuit. Looks like client functionality is working.
+16:09:24 [NOTICE] Bootstrapped 100%: Done.
+</property>
+ </object>
+</interface>
diff --git a/src/gui/controller.py b/src/gui/controller.py
new file mode 100755
index 0000000..2f54933
--- /dev/null
+++ b/src/gui/controller.py
@@ -0,0 +1,85 @@
+from util import torTools
+
+import gtk
+
+class GuiController:
+ def __init__(self):
+ filename = 'src/gui/arm.xml'
+ self.builder = gtk.Builder()
+ self.builder.add_from_file(filename)
+ self.builder.connect_signals(self)
+
+ def run(self):
+ window = self.builder.get_object('window_main')
+
+ col = self.builder.get_object('treeview_sticky').get_column(0)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'text', 0)
+
+ col = self.builder.get_object('treeview_sticky').get_column(1)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 1)
+ col.add_attribute(cell, 'foreground', 2)
+
+ col = self.builder.get_object('treeview_conn').get_column(0)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 0)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_conn').get_column(1)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 1)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_conn').get_column(2)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 2)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_conn').get_column(3)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 3)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_config').get_column(0)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 0)
+ col.add_attribute(cell, 'foreground', 3)
+
+ col = self.builder.get_object('treeview_config').get_column(1)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 1)
+ col.add_attribute(cell, 'foreground', 3)
+
+ col = self.builder.get_object('treeview_config').get_column(2)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 2)
+ col.add_attribute(cell, 'foreground', 3)
+
+ textview = self.builder.get_object('textview_log')
+ textbuffer = self.builder.get_object('textbuffer_log')
+ textview.set_buffer(textbuffer)
+
+ conn = torTools.getConn()
+ torPid = conn.getMyPid()
+ textbuffer.set_text("Tor pid: %s" % torPid)
+
+ window.show_all()
+ gtk.main()
+
+ def on_window_main_delete_event(self, widget, data=None):
+ gtk.main_quit()
+
+def startGui():
+ controller = GuiController()
+ controller.run()
+
diff --git a/src/starter.py b/src/starter.py
index b41b18b..9d7f17c 100644
--- a/src/starter.py
+++ b/src/starter.py
@@ -16,6 +16,7 @@ import platform
import version
import cli.controller
import cli.logPanel
+import gui.controller
import util.conf
import util.connections
import util.hostnames
@@ -49,11 +50,12 @@ CONFIG = {"startup.controlPassword": None,
"log.configDescriptions.persistance.saveFailed": util.log.NOTICE,
"log.savingDebugLog": util.log.NOTICE}
-OPT = "i:c:dbe:vh"
-OPT_EXPANDED = ["interface=", "config=", "debug", "blind", "event=", "version", "help"]
+OPT = "gi:c:dbe:vh"
+OPT_EXPANDED = ["gtk", "interface=", "config=", "debug", "blind", "event=", "version", "help"]
HELP_MSG = """Usage arm [OPTION]
Terminal status monitor for Tor relays.
+ -g, --gtk launch the Gtk+ interface
-i, --interface [ADDRESS:]PORT change control interface from %s:%i
-c, --config CONFIG_PATH loaded configuration options, CONFIG_PATH
defaults to: %s
@@ -208,6 +210,7 @@ def _dumpConfig():
if __name__ == '__main__':
startTime = time.time()
param = dict([(key, None) for key in CONFIG.keys()])
+ launchGui = False
isDebugMode = False
configPath = DEFAULT_CONFIG # path used for customized configuration
@@ -236,6 +239,7 @@ if __name__ == '__main__':
param["startup.interface.ipAddress"] = controlAddr
param["startup.interface.port"] = controlPort
+ elif opt in ("-g", "--gtk"): launchGui = True
elif opt in ("-c", "--config"): configPath = arg # sets path of user's config
elif opt in ("-d", "--debug"): isDebugMode = True # dumps all logs
elif opt in ("-b", "--blind"):
@@ -401,5 +405,8 @@ if __name__ == '__main__':
if util.uiTools.isUnicodeAvailable():
locale.setlocale(locale.LC_ALL, "")
- cli.controller.startTorMonitor(time.time() - initTime)
+ if launchGui == True:
+ gui.controller.startGui()
+ else:
+ cli.controller.startTorMonitor(time.time() - initTime)
[View Less]
1
0
commit bffe945d864799ef8f83f60911740958aa0c7572
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Tue Jun 7 15:31:36 2011 +0500
Add cagraph as a prereq.
---
src/prereq.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/src/prereq.py b/src/prereq.py
index 4bda913..2e26161 100644
--- a/src/prereq.py
+++ b/src/prereq.py
@@ -8,6 +8,9 @@ import shutil
import tempfile
TORCTL_REPO = "git://git.…
[View More]torproject.org/pytorctl.git"
+CAGRAPH_TARBALL_URL = "http://cagraph.googlecode.com/files/cagraph-1.2.tar.gz"
+CAGRAPH_TARBALL_NAME = "cagraph-1.2.tar.gz"
+CAGRAPH_TARBALL_ROOT = "cagraph-1.2"
def isTorCtlAvailable():
"""
@@ -20,6 +23,16 @@ def isTorCtlAvailable():
except ImportError:
return False
+def isCagraphAvailable():
+ """
+ True if cagraph is already available on the platform, false otherwise.
+ """
+ try:
+ import cagraph
+ return True
+ except ImportError:
+ return False
+
def promptTorCtlInstall():
"""
Asks the user to install TorCtl. This returns True if it was installed and
@@ -44,6 +57,30 @@ def promptTorCtlInstall():
print exc
return False
+def promptCagraphInstall():
+ """
+ Asks the user to install cagraph. This returns True if it was installed and
+ False otherwise (if it was either declined or failed to be fetched).
+ """
+
+ userInput = raw_input("Arm requires cagraph to run, but it's unavailable. Would you like to install it? (y/n): ")
+
+ # if user says no then terminate
+ if not userInput.lower() in ("y", "yes"): return False
+
+ # attempt to install TorCtl, printing the issue if unsuccessful
+ try:
+ installCagraph()
+
+ if not isCagraphAvailable():
+ raise IOError("Unable to install cagraph, sorry")
+
+ print "cagraph successfully installed"
+ return True
+ except IOError, exc:
+ print exc
+ return False
+
def installTorCtl():
"""
Checks out the current git head release for TorCtl and bundles it with arm.
@@ -71,6 +108,31 @@ def installTorCtl():
# of errors.
shutil.rmtree(tmpFilename, ignore_errors=True)
+def installCagraph():
+ """
+ Downloads and extracts the cagraph tarball.
+ This raises an IOError if unsuccessful.
+ """
+
+ if isCagraphAvailable(): return
+
+ tmpDir = tempfile.mkdtemp()
+ tmpFilename = os.path.join(tmpDir, CAGRAPH_TARBALL_NAME)
+
+ exitStatus = os.system("wget -P %s %s" % (tmpDir, CAGRAPH_TARBALL_URL))
+ if exitStatus: raise IOError("Unable to fetch cagraph from %s. Is wget installed?" % CAGRAPH_TARBALL_URL)
+
+ # the destination for TorCtl will be our directory
+ ourDir = os.path.dirname(os.path.realpath(__file__))
+
+ # exports TorCtl to our location
+ exitStatus = os.system("(cd %s && tar --strip-components=1 -xzf %s %s/cagraph)" % (ourDir, tmpFilename, CAGRAPH_TARBALL_ROOT))
+ if exitStatus: raise IOError("Unable to extract cagraph to %s" % ourDir)
+
+ # Clean up the temporary contents. This isn't vital so quietly fails in case
+ # of errors.
+ shutil.rmtree(tmpDir, ignore_errors=True)
+
if __name__ == '__main__':
majorVersion = sys.version_info[0]
minorVersion = sys.version_info[1]
@@ -92,3 +154,7 @@ if __name__ == '__main__':
isInstalled = promptTorCtlInstall()
if not isInstalled: sys.exit(1)
+ if not isCagraphAvailable():
+ isInstalled = promptCagraphInstall()
+ if not isInstalled: sys.exit(1)
+
[View Less]
1
0

10 Jun '11
commit 76ef47882a19484c498e60954f6f5310d140416d
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Sun Jun 5 21:53:23 2011 +0500
Remove repetitive cell packing inside cols.
---
src/gui/controller.py | 75 ++++++++++++++----------------------------------
1 files changed, 22 insertions(+), 53 deletions(-)
diff --git a/src/gui/controller.py b/src/gui/controller.py
index 2f54933..a4f34a0 100644
--- a/src/gui/controller.py
+++ b/src/gui/controller.py
@@ -8,63 +8,11 @@ class …
[View More]GuiController:
self.builder = gtk.Builder()
self.builder.add_from_file(filename)
self.builder.connect_signals(self)
+ self._pack_formatted_cells_into_cols()
def run(self):
window = self.builder.get_object('window_main')
- col = self.builder.get_object('treeview_sticky').get_column(0)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'text', 0)
-
- col = self.builder.get_object('treeview_sticky').get_column(1)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 1)
- col.add_attribute(cell, 'foreground', 2)
-
- col = self.builder.get_object('treeview_conn').get_column(0)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 0)
- col.add_attribute(cell, 'foreground', 4)
-
- col = self.builder.get_object('treeview_conn').get_column(1)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 1)
- col.add_attribute(cell, 'foreground', 4)
-
- col = self.builder.get_object('treeview_conn').get_column(2)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 2)
- col.add_attribute(cell, 'foreground', 4)
-
- col = self.builder.get_object('treeview_conn').get_column(3)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 3)
- col.add_attribute(cell, 'foreground', 4)
-
- col = self.builder.get_object('treeview_config').get_column(0)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 0)
- col.add_attribute(cell, 'foreground', 3)
-
- col = self.builder.get_object('treeview_config').get_column(1)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 1)
- col.add_attribute(cell, 'foreground', 3)
-
- col = self.builder.get_object('treeview_config').get_column(2)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', 2)
- col.add_attribute(cell, 'foreground', 3)
-
textview = self.builder.get_object('textview_log')
textbuffer = self.builder.get_object('textbuffer_log')
textview.set_buffer(textbuffer)
@@ -79,6 +27,27 @@ class GuiController:
def on_window_main_delete_event(self, widget, data=None):
gtk.main_quit()
+ def _pack_formatted_cells_into_cols(self):
+ self._pack_formatted_cell_into_col(treeview='treeview_sticky', col=0, markup=0)
+ self._pack_formatted_cell_into_col(treeview='treeview_sticky', col=1, markup=1, foreground=2)
+ self._pack_formatted_cell_into_col(treeview='treeview_conn', col=0, markup=0, foreground=4)
+ self._pack_formatted_cell_into_col(treeview='treeview_conn', col=1, markup=1, foreground=4)
+ self._pack_formatted_cell_into_col(treeview='treeview_conn', col=2, markup=2, foreground=4)
+ self._pack_formatted_cell_into_col(treeview='treeview_conn', col=3, markup=3, foreground=4)
+ self._pack_formatted_cell_into_col(treeview='treeview_config', col=0, markup=0, foreground=3)
+ self._pack_formatted_cell_into_col(treeview='treeview_config', col=1, markup=1, foreground=3)
+ self._pack_formatted_cell_into_col(treeview='treeview_config', col=2, markup=2, foreground=3)
+
+ def _pack_formatted_cell_into_col(self, treeview, col, markup, foreground=-1, background=-1):
+ col = self.builder.get_object(treeview).get_column(col)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', markup)
+ if foreground != -1:
+ col.add_attribute(cell, 'foreground', foreground)
+ if background != -1:
+ col.add_attribute(cell, 'background', background)
+
def startGui():
controller = GuiController()
controller.run()
[View Less]
1
0

10 Jun '11
commit eedc9eeb8941d189ed9f684400cac1630bcc5c0e
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Wed Jun 8 20:41:27 2011 +0500
Remove cell renderer packing from the controller.
GtkBuilder's internal support for connecting tree models and views
is used to clean up the program.
---
src/gui/arm.xml | 119 +++++++++++++++++++++++++++++++++----------------
src/gui/controller.py | 25 ----------
2 files changed, 80 insertions(+), 64 deletions(-)
diff --git …
[View More]a/src/gui/arm.xml b/src/gui/arm.xml
index 49ffc89..85f60d3 100644
--- a/src/gui/arm.xml
+++ b/src/gui/arm.xml
@@ -4,13 +4,11 @@
<!-- interface-naming-policy project-wide -->
<object class="GtkListStore" id="liststore_sticky">
<columns>
- <!-- column-name gchararray1 -->
+ <!-- column-name key -->
<column type="gchararray"/>
- <!-- column-name gchararray2 -->
+ <!-- column-name value -->
<column type="gchararray"/>
- <!-- column-name gchararray3 -->
- <column type="gchararray"/>
- <!-- column-name gchararray4 -->
+ <!-- column-name foreground -->
<column type="gchararray"/>
</columns>
<data>
@@ -18,71 +16,60 @@
<col id="0" translatable="yes">arm</col>
<col id="1" translatable="yes">orthanc (Linux 2.6.35.11-83.fc14)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Tor</col>
<col id="1" translatable="yes">0.2.1.28 (obsolete)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">black</col>
</row>
<row>
<col id="0" translatable="yes">Relaying</col>
<col id="1" translatable="yes">Disabled</col>
<col id="2" translatable="yes">red</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Control Port</col>
<col id="1" translatable="yes">9051 (open)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">CPU Tor</col>
<col id="1" translatable="yes">0.0%</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">CPU arm</col>
<col id="1" translatable="yes">0.0%</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Memory</col>
<col id="1" translatable="yes">20 MB (1.0%)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">PID</col>
<col id="1" translatable="yes">3980</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Uptime</col>
<col id="1" translatable="yes">01:01:34</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore_conn">
<columns>
- <!-- column-name gchararray1 -->
- <column type="gchararray"/>
- <!-- column-name gchararray2 -->
+ <!-- column-name origin -->
<column type="gchararray"/>
- <!-- column-name gchararray3 -->
+ <!-- column-name dest -->
<column type="gchararray"/>
- <!-- column-name gchararray4 -->
+ <!-- column-name time -->
<column type="gchararray"/>
- <!-- column-name gchararray5 -->
+ <!-- column-name type -->
<column type="gchararray"/>
- <!-- column-name gchararray6 -->
+ <!-- column-name foreground -->
<column type="gchararray"/>
</columns>
<data>
@@ -92,7 +79,6 @@
<col id="2" translatable="yes">10.7m</col>
<col id="3" translatable="yes">CLIENT</col>
<col id="4" translatable="yes">blue</col>
- <col id="5" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">115.167.31.237:44940</col>
@@ -100,7 +86,6 @@
<col id="2" translatable="yes">28.3m</col>
<col id="3" translatable="yes">CLIENT</col>
<col id="4" translatable="yes">blue</col>
- <col id="5" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">127.0.0.1:9051</col>
@@ -108,21 +93,18 @@
<col id="2" translatable="yes">30.0m</col>
<col id="3" translatable="yes">CONTROL</col>
<col id="4" translatable="yes">red</col>
- <col id="5" translatable="yes">white</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore_config">
<columns>
- <!-- column-name gchararray1 -->
+ <!-- column-name key -->
<column type="gchararray"/>
- <!-- column-name gchararray2 -->
+ <!-- column-name value -->
<column type="gchararray"/>
- <!-- column-name gchararray3 -->
+ <!-- column-name desc -->
<column type="gchararray"/>
- <!-- column-name gchararray4 -->
- <column type="gchararray"/>
- <!-- column-name gchararray5 -->
+ <!-- column-name foreground -->
<column type="gchararray"/>
</columns>
<data>
@@ -131,28 +113,24 @@
<col id="1" translatable="yes">5242880</col>
<col id="2" translatable="yes">Average bandwidth usage limit</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">BandwidthBurst</col>
<col id="1" translatable="yes">10485760</col>
<col id="2" translatable="yes">Maximum bandwidth usage limit</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">RelayBandwidthBurst</col>
<col id="1" translatable="yes">0 B</col>
<col id="2" translatable="yes">Maximum bandwidth usage limit for relaying</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">ControlPort</col>
<col id="1" translatable="yes">9051</col>
<col id="2" translatable="yes">Port providing access to tor controllers (arm, vidalia, etc)</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
</data>
</object>
@@ -344,7 +322,7 @@
</packing>
</child>
<child>
- <object class="GtkCurve" id="curve_graph_a">
+ <object class="GtkVBox" id="placeholder_graph_a">
<property name="visible">True</property>
</object>
<packing>
@@ -383,7 +361,7 @@
</packing>
</child>
<child>
- <object class="GtkCurve" id="curve_graph_b">
+ <object class="GtkVBox" id="placeholder_graph_b">
<property name="visible">True</property>
</object>
<packing>
@@ -446,21 +424,49 @@
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_conn_origin">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_origin"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">0</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_conn_dest">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_dest"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_conn_time">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_time"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">2</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_alive">
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_type">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_type"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">3</attribute>
+ </attributes>
+ </child>
</object>
</child>
</object>
@@ -517,18 +523,39 @@ each direction. (Default: 0) </span></property>
<property name="headers_visible">False</property>
<property name="search_column">0</property>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn_name">
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_key">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_config_key"/>
+ <attributes>
+ <attribute name="foreground">3</attribute>
+ <attribute name="markup">0</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_value">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_config_value"/>
+ <attributes>
+ <attribute name="foreground">3</attribute>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_desc">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_config_desc"/>
+ <attributes>
+ <attribute name="foreground">3</attribute>
+ <attribute name="markup">2</attribute>
+ </attributes>
+ </child>
</object>
</child>
</object>
@@ -573,13 +600,26 @@ each direction. (Default: 0) </span></property>
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_name">
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_key">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_sticky_key"/>
+ <attributes>
+ <attribute name="markup">0</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_value">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_sticky_value"/>
+ <attributes>
+ <attribute name="foreground">2</attribute>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
</object>
</child>
</object>
@@ -605,6 +645,7 @@ each direction. (Default: 0) </span></property>
<object class="GtkTextView" id="textview_log">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="buffer">textbuffer_log</property>
</object>
</child>
</object>
diff --git a/src/gui/controller.py b/src/gui/controller.py
index a4f34a0..0e444d3 100644
--- a/src/gui/controller.py
+++ b/src/gui/controller.py
@@ -8,15 +8,11 @@ class GuiController:
self.builder = gtk.Builder()
self.builder.add_from_file(filename)
self.builder.connect_signals(self)
- self._pack_formatted_cells_into_cols()
def run(self):
window = self.builder.get_object('window_main')
- textview = self.builder.get_object('textview_log')
textbuffer = self.builder.get_object('textbuffer_log')
- textview.set_buffer(textbuffer)
-
conn = torTools.getConn()
torPid = conn.getMyPid()
textbuffer.set_text("Tor pid: %s" % torPid)
@@ -27,27 +23,6 @@ class GuiController:
def on_window_main_delete_event(self, widget, data=None):
gtk.main_quit()
- def _pack_formatted_cells_into_cols(self):
- self._pack_formatted_cell_into_col(treeview='treeview_sticky', col=0, markup=0)
- self._pack_formatted_cell_into_col(treeview='treeview_sticky', col=1, markup=1, foreground=2)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=0, markup=0, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=1, markup=1, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=2, markup=2, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=3, markup=3, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_config', col=0, markup=0, foreground=3)
- self._pack_formatted_cell_into_col(treeview='treeview_config', col=1, markup=1, foreground=3)
- self._pack_formatted_cell_into_col(treeview='treeview_config', col=2, markup=2, foreground=3)
-
- def _pack_formatted_cell_into_col(self, treeview, col, markup, foreground=-1, background=-1):
- col = self.builder.get_object(treeview).get_column(col)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', markup)
- if foreground != -1:
- col.add_attribute(cell, 'foreground', foreground)
- if background != -1:
- col.add_attribute(cell, 'background', background)
-
def startGui():
controller = GuiController()
controller.run()
[View Less]
1
0
commit 681b169abf18334fc0aeb4ecea2f9bd50f43da2e
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Wed Jun 8 20:43:42 2011 +0500
Fixed comments referring to cagraph.
---
src/prereq.py | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/prereq.py b/src/prereq.py
index 2e26161..506a4b0 100644
--- a/src/prereq.py
+++ b/src/prereq.py
@@ -68,7 +68,7 @@ def promptCagraphInstall():
# if user says no then terminate
if not userInput.lower() in ("y",…
[View More] "yes"): return False
- # attempt to install TorCtl, printing the issue if unsuccessful
+ # attempt to install cagraph, printing the issue if unsuccessful
try:
installCagraph()
@@ -122,10 +122,10 @@ def installCagraph():
exitStatus = os.system("wget -P %s %s" % (tmpDir, CAGRAPH_TARBALL_URL))
if exitStatus: raise IOError("Unable to fetch cagraph from %s. Is wget installed?" % CAGRAPH_TARBALL_URL)
- # the destination for TorCtl will be our directory
+ # the destination for cagraph will be our directory
ourDir = os.path.dirname(os.path.realpath(__file__))
- # exports TorCtl to our location
+ # exports cagraph to our location
exitStatus = os.system("(cd %s && tar --strip-components=1 -xzf %s %s/cagraph)" % (ourDir, tmpFilename, CAGRAPH_TARBALL_ROOT))
if exitStatus: raise IOError("Unable to extract cagraph to %s" % ourDir)
[View Less]
1
0
commit 83512a5501cd3c76935287e7140ef6a3b5fa7f01
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Wed Jun 8 20:42:40 2011 +0500
Use --gui as the long argument.
---
src/starter.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/starter.py b/src/starter.py
index 9d7f17c..a94020f 100644
--- a/src/starter.py
+++ b/src/starter.py
@@ -55,7 +55,7 @@ OPT_EXPANDED = ["gtk", "interface=", "config=", "debug", "blind", "event=", "ver
HELP_MSG = """Usage …
[View More]arm [OPTION]
Terminal status monitor for Tor relays.
- -g, --gtk launch the Gtk+ interface
+ -g, --gui launch the Gtk+ interface
-i, --interface [ADDRESS:]PORT change control interface from %s:%i
-c, --config CONFIG_PATH loaded configuration options, CONFIG_PATH
defaults to: %s
@@ -239,7 +239,7 @@ if __name__ == '__main__':
param["startup.interface.ipAddress"] = controlAddr
param["startup.interface.port"] = controlPort
- elif opt in ("-g", "--gtk"): launchGui = True
+ elif opt in ("-g", "--gui"): launchGui = True
elif opt in ("-c", "--config"): configPath = arg # sets path of user's config
elif opt in ("-d", "--debug"): isDebugMode = True # dumps all logs
elif opt in ("-b", "--blind"):
[View Less]
1
0

[flashproxy/rtmfp] Put the resolved relay address at the top of the facilitator log.
by dcf@torproject.org 10 Jun '11
by dcf@torproject.org 10 Jun '11
10 Jun '11
commit 62049e7cb19cf014b29c6e78b9e1b67c2f3c1c5f
Author: David Fifield <david(a)bamsoftware.com>
Date: Fri Jun 10 03:42:49 2011 -0700
Put the resolved relay address at the top of the facilitator log.
---
facilitator.py | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/facilitator.py b/facilitator.py
index be7543a..7fc9484 100755
--- a/facilitator.py
+++ b/facilitator.py
@@ -345,6 +345,7 @@ class Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
…
[View More]server = Server(addrinfo[4], Handler)
log(u"start on %s" % format_addr(addrinfo[4]))
+log(u"using relay address %s" % options.relay_spec)
if options.daemonize:
log(u"daemonizing")
[View Less]
1
0
commit f2e878f6e17965b338094c0eb28106b4ae55633f
Merge: c16f7d9 dd7cfb9
Author: David Fifield <david(a)bamsoftware.com>
Date: Fri Jun 10 06:41:33 2011 -0700
Merge branch 'master' into rtmfp
Conflicts:
README
facilitator.py
swfcat.as
FacilitatorSocket.as | 39 +++++------
ProxyPair.as | 27 +++++----
README | 16 +++--
SQSProxyPair.as | 17 +----
TCPProxyPair.as …
[View More] | 17 +----
connector.py | 2 +-
design.txt | 28 ++++----
events/FacilitatorSocketEvent.as | 4 +-
facilitator.py | 130 +++++++++++++++++++++++++-------------
swfcat.as | 30 +--------
10 files changed, 157 insertions(+), 153 deletions(-)
diff --cc FacilitatorSocket.as
index 3930fea,0000000..70325c1
mode 100644,000000..100644
--- a/FacilitatorSocket.as
+++ b/FacilitatorSocket.as
@@@ -1,103 -1,0 +1,100 @@@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.HTTPStatusEvent;
+ import flash.events.IOErrorEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.URLLoader;
+ import flash.net.URLLoaderDataFormat;
+ import flash.net.URLRequest;
+ import flash.net.URLRequestMethod;
+ import flash.net.URLVariables;
+
+ import events.FacilitatorSocketEvent;
+
+ [Event(name=FacilitatorSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATION_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATION_RECEIVED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ [Event(name=FacilitatorSocketEvent.REGISTRATIONS_EMPTY, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")]
+ public class FacilitatorSocket extends EventDispatcher
+ {
+ private var host:String;
+ private var port:uint;
+
+ public function FacilitatorSocket(host:String, port:uint)
+ {
+ this.host = host;
+ this.port = port;
+ }
+
+ public function get_registration():void
+ {
+ make_request(URLRequestMethod.GET);
+ }
+
+ public function post_registration(registration_data:String):void
+ {
+ var data:URLVariables = new URLVariables();
+ data.client = registration_data;
+ make_request(URLRequestMethod.POST, data);
+ }
+
+ private function fail():void
+ {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_FAILED));
+ }
+
+ private function make_request(method:String, data:URLVariables = null):void
+ {
- var request:URLRequest = new URLRequest(url)
++ var request:URLRequest;
++ var loader:URLLoader;
++
++ loader = new URLLoader();
++ /* Get the x-www-form-encoded-values. */
++ loader.dataFormat = URLLoaderDataFormat.VARIABLES;
++ loader.addEventListener(Event.COMPLETE, on_complete_event);
++ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
++ loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
++
++ request = new URLRequest(url);
+ request.data = data;
+ request.method = method;
-
- var url_loader:URLLoader = new URLLoader();
- url_loader = new URLLoader();
- url_loader.dataFormat = URLLoaderDataFormat.VARIABLES;
-
- url_loader.addEventListener(Event.COMPLETE, on_complete_event);
- url_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, on_http_status_event);
- url_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
- url_loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
-
- url_loader.load(request);
++ loader.load(request);
+ }
+
+ private function on_complete_event(event:Event):void
+ {
+ try {
+ var client_id:String = event.target.data.client;
- if (client_id == "Registration list empty") {
++ var relay_addr:String = event.target.data.relay;
++ if (client_id == "") {
+ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY));
+ } else {
- dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id));
++ dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id, relay_addr));
+ }
+ } catch (e:Error) {
+ /* error is thrown for POST when we don't care about
+ the response anyways */
+ }
+
+ event.target.close()
+ }
+
- private function on_http_status_event(event:HTTPStatusEvent):void
- {
- /* empty for now */
- }
-
+ private function on_io_error_event(event:IOErrorEvent):void
+ {
+ fail();
+ }
+
+ private function on_security_error_event(event:SecurityErrorEvent):void
+ {
+ fail();
+ }
+
+ private function get url():String
+ {
- return "http://" + host + ":" + port;
++ return "http://" + encodeURIComponent(host)
++ + ":" + encodeURIComponent(port.toString()) + "/";
+ }
+ }
- }
++}
diff --cc ProxyPair.as
index 75ae901,0000000..6ca60ef
mode 100644,000000..100644
--- a/ProxyPair.as
+++ b/ProxyPair.as
@@@ -1,273 -1,0 +1,276 @@@
+package
+{
+ import flash.errors.IllegalOperationError;
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
++ import flash.events.TextEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+ import flash.utils.clearTimeout;
+ import flash.utils.setTimeout;
+
+ import swfcat;
+
+ public class ProxyPair extends EventDispatcher
+ {
+ private var ui:swfcat;
+
+ protected var client_addr:Object;
+
+ /* Not defined here: subclasses should define their own
+ * protected var client_socket:Object;
+ */
+
+ private var c2r_schedule:Array;
+
+ private var relay_addr:Object;
+ private var relay_socket:Socket;
+ private var r2c_schedule:Array;
+
+ // Bytes per second. Set to undefined to disable limit.
+ private const RATE_LIMIT:Number = undefined; //10000;
+ // Seconds.
+ private const RATE_LIMIT_HISTORY:Number = 5.0;
+
+ private var rate_limit:RateLimit;
+
+ // Callback id.
+ private var flush_id:uint;
+
+ public function ProxyPair(self:ProxyPair, ui:swfcat)
+ {
+ if (self != this) {
+ //only a subclass can pass a valid reference to self
+ throw new IllegalOperationError("ProxyPair cannot be instantiated directly.");
+ }
+
+ this.ui = ui;
+ this.c2r_schedule = new Array();
+ this.r2c_schedule = new Array();
+
+ if (RATE_LIMIT)
+ rate_limit = new BucketRateLimit(RATE_LIMIT * RATE_LIMIT_HISTORY, RATE_LIMIT_HISTORY);
+ else
+ rate_limit = new RateUnlimit();
+
+ setup_relay_socket();
+
+ /* client_socket setup should be taken */
+ /* care of in the subclass constructor */
+ }
+
+ public function close():void
+ {
+ if (relay_socket != null && relay_socket.connected) {
+ relay_socket.close();
+ }
+
+ /* subclasses should override to close */
+ /* their client_socket according to impl. */
+ }
+
+ public function get connected():Boolean
+ {
+ return (relay_socket != null && relay_socket.connected);
+
+ /* subclasses should override to check */
+ /* connectivity of their client_socket. */
+ }
+
+ public function set client(client_addr:Object):void
+ {
+ /* subclasses should override to */
+ /* connect the client_socket here */
+ }
+
+ public function set relay(relay_addr:Object):void
+ {
+ this.relay_addr = relay_addr;
+ log("Relay: connecting to " + relay_addr.host + ":" + relay_addr.port + ".");
+ relay_socket.connect(relay_addr.host, relay_addr.port);
+ }
+
+ protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ /* No-op: must be overridden by subclasses */
+ }
++
++ protected function socket_error(message:String):Function
++ {
++ return function(e:Event):void {
++ if (e is TextEvent)
++ log(message + ": " + (e as TextEvent).text + ".");
++ else
++ log(message + ".");
++ close();
++ };
++ }
+
+ private function setup_relay_socket():void
+ {
+ relay_socket = new Socket();
+ relay_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Relay: connected to " + relay_addr.host + ":" + relay_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
- relay_socket.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Relay: closed connection.");
- close();
- });
- relay_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Relay: I/O error: " + e.text + ".");
- close();
- });
- relay_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Relay: security error: " + e.text + ".");
- close();
- });
++ relay_socket.addEventListener(Event.CLOSE, socket_error("Relay: closed"));
++ relay_socket.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Relay: I/O error"))
++ relay_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Relay: security error"))
+ relay_socket.addEventListener(ProgressEvent.SOCKET_DATA, relay_to_client);
+ }
+
+ protected function client_to_relay(e:ProgressEvent):void
+ {
+ c2r_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ private function relay_to_client(e:ProgressEvent):void
+ {
+ r2c_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ /* Send as much data as the rate limit currently allows. */
+ private function flush():void
+ {
+ if (flush_id)
+ clearTimeout(flush_id);
+ flush_id = undefined;
+
+ if (!connected)
+ /* Can't do anything until connected. */
+ return;
+
+ while (!rate_limit.is_limited() && (c2r_schedule.length > 0 || r2c_schedule.length > 0)) {
+ var num_bytes:uint;
+
+ if (c2r_schedule.length > 0) {
+ num_bytes = c2r_schedule.shift();
+ transfer_bytes(null, relay_socket, num_bytes);
+ rate_limit.update(num_bytes);
+ }
+
+ if (r2c_schedule.length > 0) {
+ num_bytes = r2c_schedule.shift();
+ transfer_bytes(relay_socket, null, num_bytes);
+ rate_limit.update(num_bytes);
+ }
+ }
+
+ /* Call again when safe, if necessary. */
+ if (c2r_schedule.length > 0 || r2c_schedule.length > 0)
+ flush_id = setTimeout(flush, rate_limit.when() * 1000);
+ }
+
+ /* Helper function to write output to the
+ * swfcat console. Set as protected for
+ * subclasses */
+ protected function log(s:String):void
+ {
+ ui.puts(s);
+ }
+ }
+}
+
+import flash.utils.getTimer;
+
+class RateLimit
+{
+ public function RateLimit()
+ {
+ }
+
+ public function update(n:Number):Boolean
+ {
+ return true;
+ }
+
+ public function when():Number
+ {
+ return 0.0;
+ }
+
+ public function is_limited():Boolean
+ {
+ return false;
+ }
+}
+
+class RateUnlimit extends RateLimit
+{
+ public function RateUnlimit()
+ {
+ }
+
+ public override function update(n:Number):Boolean
+ {
+ return true;
+ }
+
+ public override function when():Number
+ {
+ return 0.0;
+ }
+
+ public override function is_limited():Boolean
+ {
+ return false;
+ }
+}
+
+class BucketRateLimit extends RateLimit
+{
+ private var amount:Number;
+ private var capacity:Number;
+ private var time:Number;
+ private var last_update:uint;
+
+ public function BucketRateLimit(capacity:Number, time:Number)
+ {
+ this.amount = 0.0;
+ /* capacity / time is the rate we are aiming for. */
+ this.capacity = capacity;
+ this.time = time;
+ this.last_update = getTimer();
+ }
+
+ private function age():void
+ {
+ var now:uint;
+ var delta:Number;
+
+ now = getTimer();
+ delta = (now - last_update) / 1000.0;
+ last_update = now;
+
+ amount -= delta * capacity / time;
+ if (amount < 0.0)
+ amount = 0.0;
+ }
+
+ public override function update(n:Number):Boolean
+ {
+ age();
+ amount += n;
+
+ return amount <= capacity;
+ }
+
+ public override function when():Number
+ {
+ age();
+ return (amount - capacity) / (capacity / time);
+ }
+
+ public override function is_limited():Boolean
+ {
+ age();
+ return amount > capacity;
+ }
+}
diff --cc README
index 05cd676,b4b1d0e..0e2a0eb
--- a/README
+++ b/README
@@@ -102,26 -81,25 +102,30 @@@ changing pool of addresses
== Design notes
- The Tor relay address is hardcoded in rtmfpcat.as. It could be any relay,
- with the caveat that the server also has to serve a crossdomain policy.
+ Any Tor relay can be used, as long as it also serves a crossdomain
+ policy.
- Client rtmfpcats register with the facilitator by sending an HTTP-like message:
-The Tor client needs to be able to listen for an incoming connection,
-which generally means not being behind NAT.
-
+ Clients register with the facilitator by sending an HTTP message:
POST / HTTP/1.0\r\n
\r\n
- client=:9000
+ client=<CIRRUS-CLIENT-ID>
+
+The <CIRRUS-CLIENT-ID> is returned by Adobe's developer Cirrus server
+as soon as the rtfmpcat can connect to it. Each rtmfpcat needs to connect
+to a server like this to get one of these client IDs, since the Cirrus
+server uses these to coordinate RTMFP connections (including NAT punching).
+The need to communicate with a Cirrus server in addition to a facilitator is
+one of the major weaknesses of this design.
+
- The proxy rtmfpcat gets a client id using something like HTTP:
+ The Flash proxy also gets a client address over HTTP:
GET / HTTP/1.0\r\n
\r\n
- The server sends back an id specification (no HTTP header):
- 51ae8ed56c3705e4ad3755cdd3328c27720984778bfff71d9ec9f2647331d39b
+ The server sends back address specifications of a client and a relay in
+ an HTTP respose.
+ HTTP/1.0 200 OK\r\n
+ Server: BaseHTTP/0.3 Python/2.5.2\r\n
+ \r\n
- client=1.2.3.4%3A9000&relay=9.9.9.9:9001
++ client=<CIRRUS-CLIENT-ID>&relay=9.9.9.9:9001
== ActionScript programming
diff --cc SQSProxyPair.as
index 54f763d,0000000..20a6a65
mode 100644,000000..100644
--- a/SQSProxyPair.as
+++ b/SQSProxyPair.as
@@@ -1,86 -1,0 +1,77 @@@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+
+ public class SQSProxyPair extends ProxyPair
+ {
+ private var client_socket:Socket;
+
+ public function SQSProxyPair(ui:swfcat)
+ {
+ super(this, ui);
+
+ log("Starting SQS proxy pair");
+ setup_client_socket();
+ }
+
+ override public function set client(client_addr:Object):void
+ {
+ this.client_addr = client_addr;
+ log("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
+ client_socket.connect(client_addr.host, client_addr.port);
+ }
+
+ override public function close():void
+ {
+ super.close();
+ if (client_socket != null && client_socket.connected) {
+ client_socket.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ override public function get connected():Boolean
+ {
+ return (super.connected && client_socket != null && client_socket.connected);
+ }
+
+ override protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ var bytes:ByteArray = new ByteArray();
+
+ if (src == null) {
+ src = client_socket;
+ }
+
+ if (dst == null) {
+ dst = client_socket;
+ }
+
+ Socket(src).readBytes(bytes, 0, num_bytes);
+ log("SQSProxyPair: transferring " + num_bytes + " bytes.");
+ Socket(dst).writeBytes(bytes);
+ }
+
+ private function setup_client_socket():void
+ {
+ client_socket = new Socket();
+
+ client_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Client: connected to " + client_addr.host + ":" + client_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
- client_socket.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Client: closed.");
- close();
- });
- client_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Client: I/O error: " + e.text + ".");
- close();
- });
- client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Client: security error: " + e.text + ".");
- close();
- });
++ client_socket.addEventListener(Event.CLOSE, socket_error("Client: closed"));
++ client_socket.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Client: I/O error"));
++ client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Client: security error"))
+ client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+ }
+ }
- }
++}
diff --cc TCPProxyPair.as
index b81af3e,0000000..de18dd6
mode 100644,000000..100644
--- a/TCPProxyPair.as
+++ b/TCPProxyPair.as
@@@ -1,86 -1,0 +1,77 @@@
+package
+{
+ import flash.events.Event;
+ import flash.events.EventDispatcher;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+
+ public class TCPProxyPair extends ProxyPair
+ {
+ private var client_socket:Socket;
+
+ public function TCPProxyPair(ui:swfcat)
+ {
+ super(this, ui);
+
+ log("Starting TCP proxy pair");
+ setup_client_socket();
+ }
+
+ override public function set client(client_addr:Object):void
+ {
+ this.client_addr = client_addr;
+ log("Client: connecting to " + client_addr.host + ":" + client_addr.port + ".");
+ client_socket.connect(client_addr.host, client_addr.port);
+ }
+
+ override public function close():void
+ {
+ super.close();
+ if (client_socket != null && client_socket.connected) {
+ client_socket.close();
+ }
+ dispatchEvent(new Event(Event.CLOSE));
+ }
+
+ override public function get connected():Boolean
+ {
+ return (super.connected && client_socket != null && client_socket.connected);
+ }
+
+ override protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+ {
+ var bytes:ByteArray = new ByteArray();
+
+ if (src == null) {
+ src = client_socket;
+ }
+
+ if (dst == null) {
+ dst = client_socket;
+ }
+
+ Socket(src).readBytes(bytes, 0, num_bytes);
+ log("TCPProxyPair: transferring " + num_bytes + " bytes.");
+ Socket(dst).writeBytes(bytes);
+ }
+
+ private function setup_client_socket():void
+ {
+ client_socket = new Socket();
+
+ client_socket.addEventListener(Event.CONNECT, function (e:Event):void {
+ log("Client: connected to " + client_addr.host + ":" + client_addr.port + ".");
+ if (connected) {
+ dispatchEvent(new Event(Event.CONNECT));
+ }
+ });
- client_socket.addEventListener(Event.CLOSE, function (e:Event):void {
- log("Client: closed.");
- close();
- });
- client_socket.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- log("Client: I/O error: " + e.text + ".");
- close();
- });
- client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- log("Client: security error: " + e.text + ".");
- close();
- });
++ client_socket.addEventListener(Event.CLOSE, socket_error("Client: closed"));
++ client_socket.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Client: I/O error"));
++ client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Client: security error"))
+ client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+ }
+ }
- }
++}
diff --cc events/FacilitatorSocketEvent.as
index 9fc478b,0000000..5787309
mode 100644,000000..100644
--- a/events/FacilitatorSocketEvent.as
+++ b/events/FacilitatorSocketEvent.as
@@@ -1,22 -1,0 +1,24 @@@
+package events
+{
+ import flash.events.Event;
+
+ public class FacilitatorSocketEvent extends Event
+ {
+ public static const CONNECT_CLOSED:String = "connectClosed";
+ public static const CONNECT_FAILED:String = "connectFailed";
+ public static const CONNECT_SUCCESS:String = "connectSuccess";
+ public static const REGISTRATION_RECEIVED:String = "registrationReceived";
+ public static const REGISTRATION_FAILED:String = "registrationFailed";
+ public static const REGISTRATIONS_EMPTY:String = "registrationsEmpty";
+
+ public var client:String;
++ public var relay:String;
+
- public function FacilitatorSocketEvent(type:String, client:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
++ public function FacilitatorSocketEvent(type:String, client:String = null, relay:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
+ {
+ super(type, bubbles, cancelable);
+ this.client = client;
++ this.relay = relay;
+ }
+ }
+}
diff --cc swfcat.as
index 1bb2ff5,4aa430b..dd2396d
--- a/swfcat.as
+++ b/swfcat.as
@@@ -5,64 -5,33 +5,56 @@@ packag
import flash.display.StageScaleMode;
import flash.text.TextField;
import flash.text.TextFormat;
- import flash.net.Socket;
- import flash.net.URLLoader;
- import flash.net.URLLoaderDataFormat;
- import flash.net.URLRequest;
import flash.events.Event;
- import flash.events.IOErrorEvent;
- import flash.events.ProgressEvent;
- import flash.events.SecurityErrorEvent;
- import flash.utils.ByteArray;
import flash.utils.setTimeout;
+ import FacilitatorSocket;
+ import events.FacilitatorSocketEvent;
+
+ import ProxyPair;
+ import RTMFPProxyPair;
+ import SQSProxyPair;
+ import TCPProxyPair;
+
+ import rtmfp.CirrusSocket;
+ import rtmfp.events.CirrusSocketEvent;
+
public class swfcat extends Sprite
{
+ /* Adobe's Cirrus server for RTMFP connections.
+ The Cirrus key is defined at compile time by
+ reading from the CIRRUS_KEY environment var. */
+ private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
+ private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
+
- /* David's facilitator. */
private const DEFAULT_FACILITATOR_ADDR:Object = {
- host: "173.255.221.44",
+ host: "tor-facilitator.bamsoftware.com",
port: 9002
};
-
- private const MAX_NUM_PROXY_PAIRS:uint = 1;
-
- // Milliseconds.
- private const FACILITATOR_POLL_INTERVAL:int = 10000;
-
- // Bytes per second. Set to undefined to disable limit.
- public const RATE_LIMIT:Number = undefined;
- // Seconds.
- private const RATE_LIMIT_HISTORY:Number = 5.0;
+
+ /* Default Tor client to use in case of RTMFP connection */
+ private const DEFAULT_TOR_CLIENT_ADDR:Object = {
+ host: "127.0.0.1",
+ port: 9002
+ };
+
- /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
- crossdomain policy. */
- private const DEFAULT_TOR_RELAY_ADDR:Object = {
- host: "173.255.221.44",
- port: 9001
- };
-
+ /* Poll facilitator every 10 sec */
+ private const DEFAULT_FAC_POLL_INTERVAL:uint = 10000;
+
+ // Socket to Cirrus server
+ private var s_c:CirrusSocket;
+ // Socket to facilitator.
+ private var s_f:FacilitatorSocket;
+ // Handle local-remote traffic
+ private var p_p:ProxyPair;
+
+ private var client_id:String;
+ private var proxy_pair_factory:Function;
+
+ private var proxy_pairs:Array;
+
+ private var debug_mode:Boolean;
+ private var proxy_mode:Boolean;
/* TextField for debug output. */
private var output_text:TextField;
@@@ -97,57 -133,24 +89,39 @@@
private function loaderinfo_complete(e:Event):void
{
var fac_spec:String;
+ var relay_spec:String;
- puts("Parameters loaded.");
-
- if (this.loaderInfo.parameters["debug"])
+ debug_mode = (this.loaderInfo.parameters["debug"] != null)
+ proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
+ if (proxy_mode && !debug_mode) {
+ badge = new InternetFreedomBadge(this);
+ badge.display();
+ } else {
+ output_text = new TextField();
+ output_text.width = stage.stageWidth;
+ output_text.height = stage.stageHeight;
+ output_text.background = true;
+ output_text.backgroundColor = 0x001f0f;
+ output_text.textColor = 0x44cc44;
addChild(output_text);
- else {
- addChild(new BadgeImage());
- /* Tried unsuccessfully to add counter to badge. */
- /* For now, need two addChilds :( */
- addChild(tot_client_count_tf);
- addChild(cur_client_count_tf);
}
-
- fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
- if (!fac_addr) {
- puts("Error: Facilitator spec must be in the form \"host:port\".");
- return;
+
+ puts("Starting: parameters loaded.");
+
+ /* TODO: use this to have multiple proxies going at once */
+ proxy_pairs = new Array();
+
+ fac_spec = this.loaderInfo.parameters["facilitator"];
+ if (fac_spec) {
+ puts("Facilitator spec: \"" + fac_spec + "\"");
+ fac_addr = parse_addr_spec(fac_spec);
+ if (!fac_addr) {
+ puts("Error: Facilitator spec must be in the form \"host:port\".");
+ return;
+ }
+ } else {
+ fac_addr = DEFAULT_FACILITATOR_ADDR;
}
-
- /* TODO: modify this for the client so that it can specify
- a relay for the proxy to use */
- relay_spec = this.loaderInfo.parameters["relay"];
- if (relay_spec) {
- puts("Relay spec: \"" + relay_spec + "\"");
- relay_addr = parse_addr_spec(relay_spec);
- if (!relay_addr) {
- puts("Error: Relay spec must be in the form \"host:port\".");
- return;
- }
- } else {
- if (proxy_mode) {
- relay_addr = DEFAULT_TOR_RELAY_ADDR;
- } else {
- relay_addr = DEFAULT_TOR_CLIENT_ADDR;
- }
- }
main();
}
@@@ -155,132 -158,98 +129,134 @@@
/* The main logic begins here, after start-up issues are taken care of. */
private function main():void
{
- var fac_url:String;
- var loader:URLLoader;
-
- if (num_proxy_pairs >= MAX_NUM_PROXY_PAIRS) {
- setTimeout(main, FACILITATOR_POLL_INTERVAL);
- return;
+ if (proxy_mode) {
+ establish_facilitator_connection();
+ } else {
+ establish_cirrus_connection();
}
+ }
- loader = new URLLoader();
- /* Get the x-www-form-urlencoded values. */
- loader.dataFormat = URLLoaderDataFormat.VARIABLES;
- loader.addEventListener(Event.COMPLETE, fac_complete);
- loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
- puts("Facilitator: I/O error: " + e.text + ".");
+ private function establish_cirrus_connection():void
+ {
+ s_c = new CirrusSocket();
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_SUCCESS, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: connected with id " + s_c.id + ".");
+ if (proxy_mode) {
+ start_proxy_pair();
+ s_c.send_hello(client_id);
+ } else {
+ establish_facilitator_connection();
+ }
});
- loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
- puts("Facilitator: security error: " + e.text + ".");
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
+ puts("Error: failed to connect to Cirrus.");
});
-
- fac_url = "http://" + encodeURIComponent(fac_addr.host)
- + ":" + encodeURIComponent(fac_addr.port) + "/";
- puts("Facilitator: connecting to " + fac_url + ".");
- loader.load(new URLRequest(fac_url));
+ s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: closed connection.");
+ });
+ s_c.addEventListener(CirrusSocketEvent.HELLO_RECEIVED, function (e:CirrusSocketEvent):void {
+ puts("Cirrus: received hello from peer " + e.peer);
+
+ /* don't bother if we already have a proxy going */
+ if (p_p != null && p_p.connected) {
+ return;
+ }
+
+ /* if we're in proxy mode, we should have already set
+ up a proxy pair */
+ if (!proxy_mode) {
++ relay_addr = DEFAULT_TOR_CLIENT_ADDR;
+ proxy_pair_factory = rtmfp_proxy_pair_factory;
+ start_proxy_pair();
+ s_c.send_hello(e.peer);
+ } else if (!debug_mode && badge != null) {
+ badge.total_proxy_pairs++;
+ badge.num_proxy_pairs++;
+ }
+
+ p_p.client = {peer: e.peer, stream: e.stream};
+ });
+
+ s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
}
- private function fac_complete(e:Event):void
+ private function establish_facilitator_connection():void
{
- var loader:URLLoader;
- var client_spec:String;
- var client_addr:Object;
- var relay_spec:String;
- var relay_addr:Object;
- var proxy_pair:Object;
-
- setTimeout(main, FACILITATOR_POLL_INTERVAL);
-
- loader = e.target as URLLoader;
- client_spec = loader.data.client;
- if (client_spec == "") {
- puts("No clients.");
- return;
- } else if (!client_spec) {
- puts("Error: missing \"client\" in response.");
- return;
- }
- relay_spec = loader.data.relay;
- if (!relay_spec) {
- puts("Error: missing \"relay\" in response.");
- return;
- }
- puts("Facilitator: got client:\"" + client_spec + "\" "
- + "relay:\"" + relay_spec + "\".");
-
- client_addr = parse_addr_spec(client_spec);
- if (!client_addr) {
- puts("Error: Client spec must be in the form \"host:port\".");
- return;
- }
- relay_addr = parse_addr_spec(relay_spec);
- if (!client_addr) {
- puts("Error: Relay spec must be in the form \"host:port\".");
- return;
+ s_f = new FacilitatorSocket(fac_addr.host, fac_addr.port);
+ s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
+ puts("Facilitator: connect failed.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+
+ if (proxy_mode) {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void {
+ var client_addr:Object = parse_addr_spec(e.client);
++ relay_addr = parse_addr_spec(e.relay);
+ if (client_addr == null) {
+ puts("Facilitator: got registration " + e.client);
+ proxy_pair_factory = rtmfp_proxy_pair_factory;
+ if (s_c == null || !s_c.connected) {
+ client_id = e.client;
+ establish_cirrus_connection();
+ } else {
+ start_proxy_pair();
+ s_c.send_hello(e.client);
+ }
+ } else {
+ proxy_pair_factory = tcp_proxy_pair_factory;
+ start_proxy_pair();
+ p_p.client = client_addr;
+ }
+ });
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATIONS_EMPTY, function (e:Event):void {
+ puts("Facilitator: no registrations available.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+ puts("Facilitator: getting registration.");
+ s_f.get_registration();
+ } else {
+ s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
+ puts("Facilitator: registration failed.");
+ setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
+ });
+ puts("Facilitator: posting registration.");
+ s_f.post_registration(s_c.id);
}
-
- num_proxy_pairs++;
- total_proxy_pairs++;
- /* Update the client count on the badge. */
- update_client_count();
-
- proxy_pair = new ProxyPair(this, client_addr, relay_addr);
- proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
- proxy_pair.log("Complete.");
-
- num_proxy_pairs--;
- /* Update the client count on the badge. */
- update_client_count();
+ }
+
+ private function start_proxy_pair():void
+ {
+ p_p = proxy_pair_factory();
+ p_p.addEventListener(Event.CONNECT, function (e:Event):void {
+ puts("ProxyPair: connected!");
});
- proxy_pair.connect();
-
+ p_p.addEventListener(Event.CLOSE, function (e:Event):void {
+ puts("ProxyPair: connection closed.");
+ p_p = null;
+ if (proxy_mode && !debug_mode && badge != null) {
+ badge.num_proxy_pairs--;
+ }
+ establish_facilitator_connection();
+ });
+ p_p.relay = relay_addr;
+ }
+
+ private function rtmfp_proxy_pair_factory():ProxyPair
+ {
+ return new RTMFPProxyPair(this, s_c, s_c.local_stream_name);
+ }
+
+ // currently is the same as TCPProxyPair
+ // could be interesting to see how this works
+ // can't imagine it will work terribly well...
+ private function sqs_proxy_pair_factory():ProxyPair
+ {
+ return new SQSProxyPair(this);
+ }
+
+ private function tcp_proxy_pair_factory():ProxyPair
+ {
+ return new TCPProxyPair(this);
}
/* Parse an address in the form "host:port". Returns an Object with
[View Less]
1
0