tor-commits
Threads by month
- ----- 2026 -----
- 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
- 215456 discussions
12 Jun '11
commit 7ac29e5a57feb990c90834b81994aef6b8f36198
Author: Tomas Touceda <chiiph(a)torproject.org>
Date: Sat Jun 11 13:49:44 2011 -0300
Fix layout to adapt to any label length
---
src/vidalia/bwgraph/BandwidthGraph.ui | 748 ++++++++++++++-------------------
1 files changed, 311 insertions(+), 437 deletions(-)
diff --git a/src/vidalia/bwgraph/BandwidthGraph.ui b/src/vidalia/bwgraph/BandwidthGraph.ui
index 76a5a31..f05e7b9 100644
--- a/src/vidalia/bwgraph/BandwidthGraph.ui
+++ b/src/vidalia/bwgraph/BandwidthGraph.ui
@@ -6,66 +6,325 @@
<rect>
<x>0</x>
<y>0</y>
- <width>588</width>
- <height>437</height>
+ <width>593</width>
+ <height>487</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="GraphFrame" name="frmGraph">
- <property name="minimumSize">
- <size>
- <width>120</width>
- <height>80</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>10</pointsize>
- </font>
- </property>
- <property name="contextMenuPolicy">
- <enum>Qt::NoContextMenu</enum>
- </property>
- <property name="frameShape">
- <enum>QFrame::Box</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Plain</enum>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Expanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="rightMargin">
+ <number>12</number>
+ </property>
+ <property name="bottomMargin">
+ <number>12</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="GraphFrame" name="frmGraph">
+ <property name="minimumSize">
+ <size>
+ <width>120</width>
+ <height>80</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ </widget>
</item>
- <item>
- <layout class="QHBoxLayout">
- <property name="spacing">
- <number>6</number>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QFrame" name="frmSettings">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
</property>
- <property name="margin">
- <number>0</number>
+ <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="../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="../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">
+ <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_2">
+ <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">
+ <layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="btnToggleSettings">
<property name="text">
@@ -98,391 +357,6 @@
</item>
</layout>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QFrame" name="frmSettings">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>355</width>
- <height>85</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>82</height>
- </size>
- </property>
- <property name="contextMenuPolicy">
- <enum>Qt::NoContextMenu</enum>
- </property>
- <property name="frameShape">
- <enum>QFrame::StyledPanel</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Raised</enum>
- </property>
- <layout class="QHBoxLayout" name="_2">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="margin">
- <number>9</number>
- </property>
- <item>
- <layout class="QVBoxLayout" name="_3">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="margin">
- <number>3</number>
- </property>
- <item>
- <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>
- <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>
- <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>
- <spacer>
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>21</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="_4">
- <property name="spacing">
- <number>1</number>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- <item>
- <layout class="QHBoxLayout" name="_5">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- <item>
- <spacer>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="lblGraphStyle">
- <property name="text">
- <string>Style</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QComboBox" name="cmbGraphStyle">
- <item>
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="../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="../res/vidalia.qrc">
- <normaloff>:/images/16x16/graph-area.png</normaloff>:/images/16x16/graph-area.png</iconset>
- </property>
- </item>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QFrame" name="frmOpacity">
- <property name="contextMenuPolicy">
- <enum>Qt::NoContextMenu</enum>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <property name="frameShadow">
- <enum>QFrame::Plain</enum>
- </property>
- <layout class="QVBoxLayout" name="_6">
- <property name="spacing">
- <number>3</number>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- <item>
- <widget class="QSlider" name="sldrOpacity">
- <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>
- <spacer>
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="_7">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- <item>
- <spacer>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>21</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <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>
- </widget>
- </item>
- <item>
- <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>
- <spacer>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>21</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer>
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>21</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <spacer>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>21</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QVBoxLayout" name="_8">
- <property name="spacing">
- <number>1</number>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- <item>
- <widget class="QPushButton" name="btnSaveSettings">
- <property name="text">
- <string>Save</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnCancelSettings">
- <property name="text">
- <string>Cancel</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <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>
- </item>
</layout>
</widget>
<customwidgets>
1
0
commit 1a879b27c8d57aabcc8c13be9fd6cc0bc4ab862f
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 02:37:12 2011 -0700
Whitespace.
---
swfcat.as | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index 9739419..67d60a0 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -23,12 +23,12 @@ package
reading from the CIRRUS_KEY environment var. */
private const CIRRUS_URL:String = "rtmfp://p2p.rtmfp.net";
private const CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
-
+
private const DEFAULT_FACILITATOR_ADDR:Object = {
host: "tor-facilitator.bamsoftware.com",
port: 9002
};
-
+
/* Local Tor client to use in case of RTMFP connection. */
private const LOCAL_TOR_CLIENT_ADDR:Object = {
host: "127.0.0.1",
1
0
12 Jun '11
commit 9cef884c60fa5c4cea7eb1fa092c9fb53a8a1550
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 21:41:41 2011 -0700
Rewrite ProxyPair to be more generic.
---
ProxyPair.as | 204 +++++++++++++++++++++++++++-------------------------------
1 files changed, 95 insertions(+), 109 deletions(-)
diff --git a/ProxyPair.as b/ProxyPair.as
index fa51933..ca9f092 100644
--- a/ProxyPair.as
+++ b/ProxyPair.as
@@ -1,6 +1,5 @@
package
{
- import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
@@ -11,119 +10,122 @@ package
import flash.utils.ByteArray;
import flash.utils.clearTimeout;
import flash.utils.setTimeout;
-
- import swfcat;
-
+
+ /* An instance of a client-relay connection. */
public class ProxyPair extends EventDispatcher
{
+ // Socket to client.
+ private var s_c:*;
+ private var connect_c:Function;
+
+ // Socket to relay.
+ private var s_r:*;
+ private var connect_r:Function;
+
+ // Parent swfcat, for UI updates and rate meter.
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;
+
+ // Pending byte read counts for relay and client sockets.
private var r2c_schedule:Array;
-
+ private var c2r_schedule:Array;
// 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();
-
- 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
+
+ public function log(msg:String):void
{
- /* subclasses should override to */
- /* connect the client_socket here */
+ ui.puts(id() + ": " + msg)
}
-
- public function set relay(relay_addr:Object):void
+
+ // String describing this pair for output.
+ public function id():String
{
- this.relay_addr = relay_addr;
- log("Relay: connecting to " + relay_addr.host + ":" + relay_addr.port + ".");
- relay_socket.connect(relay_addr.host, relay_addr.port);
+ return "<>";
}
-
- protected function transfer_bytes(src:Object, dst:Object, num_bytes:uint):void
+
+ public function ProxyPair(ui:swfcat, s_c:*, connect_c:Function, s_r:*, connect_r:Function)
{
- /* No-op: must be overridden by subclasses */
+ this.ui = ui;
+ /* s_c is a socket for connecting to the client. connect_c is a
+ function that, when called, connects s_c. Likewise for s_r and
+ connect_r. */
+ this.s_c = s_c;
+ this.connect_c = connect_c;
+ this.s_r = s_r;
+ this.connect_r = connect_r;
+
+ this.c2r_schedule = [];
+ this.r2c_schedule = [];
}
- protected function socket_error(message:String):Function
+ /* Return a function that shows an error message and closes the other half
+ of a communication pair. */
+ private function socket_error(message:String, other:*):Function
{
return function(e:Event):void {
if (e is TextEvent)
log(message + ": " + (e as TextEvent).text + ".");
else
log(message + ".");
- close();
+ if (other && other.connected)
+ other.close();
+ dispatchEvent(new Event(Event.COMPLETE));
};
}
-
- private function setup_relay_socket():void
+
+ public function connect():void
+ {
+ s_r.addEventListener(Event.CONNECT, relay_connected);
+ s_r.addEventListener(Event.CLOSE, socket_error("Relay: closed", s_c));
+ s_r.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Relay: I/O error", s_c));
+ s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Relay: security error", s_c));
+ s_r.addEventListener(ProgressEvent.SOCKET_DATA, relay_to_client);
+
+ s_c.addEventListener(Event.CONNECT, client_connected);
+ s_c.addEventListener(Event.CLOSE, socket_error("Client: closed", s_r));
+ s_c.addEventListener(IOErrorEvent.IO_ERROR, socket_error("Client: I/O error", s_r));
+ s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socket_error("Client: security error", s_r));
+ s_c.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
+
+ log("Relay: connecting.");
+ connect_r();
+ log("Client: connecting.");
+ connect_c();
+ }
+
+ private function relay_connected(e:Event):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, 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);
+ log("Relay: connected.");
}
-
- protected function client_to_relay(e:ProgressEvent):void
+
+ private function client_connected(e:Event):void
{
- c2r_schedule.push(e.bytesLoaded);
- flush();
+ log("Client: connected.");
}
-
+
private function relay_to_client(e:ProgressEvent):void
{
r2c_schedule.push(e.bytesLoaded);
flush();
}
-
+
+ private function client_to_relay(e:ProgressEvent):void
+ {
+ c2r_schedule.push(e.bytesLoaded);
+ flush();
+ }
+
+ private function transfer_chunk(s_from:*, s_to:*, n:uint,
+ label:String):void
+ {
+ var bytes:ByteArray;
+
+ bytes = new ByteArray();
+ s_from.readBytes(bytes, 0, n);
+ s_to.writeBytes(bytes);
+ ui.rate_limit.update(n);
+ log(label + ": read " + bytes.length + ".");
+ }
+
/* Send as much data as the rate limit currently allows. */
private function flush():void
{
@@ -131,37 +133,21 @@ package
clearTimeout(flush_id);
flush_id = undefined;
- if (!connected)
- /* Can't do anything until connected. */
+ if (!(s_r.connected && s_c.connected))
+ /* Can't do anything until both sockets are connected. */
return;
- while (!ui.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);
- ui.rate_limit.update(num_bytes);
- }
-
- if (r2c_schedule.length > 0) {
- num_bytes = r2c_schedule.shift();
- transfer_bytes(relay_socket, null, num_bytes);
- ui.rate_limit.update(num_bytes);
- }
+ while (!ui.rate_limit.is_limited() &&
+ (r2c_schedule.length > 0 || c2r_schedule.length > 0)) {
+ if (r2c_schedule.length > 0)
+ transfer_chunk(s_r, s_c, r2c_schedule.shift(), "Relay");
+ if (c2r_schedule.length > 0)
+ transfer_chunk(s_c, s_r, c2r_schedule.shift(), "Client");
}
/* Call again when safe, if necessary. */
- if (c2r_schedule.length > 0 || r2c_schedule.length > 0)
+ if (r2c_schedule.length > 0 || c2r_schedule.length > 0)
flush_id = setTimeout(flush, ui.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);
- }
}
}
1
0
commit ca61c5d4125c4991468a36ef8cf6e9fb23d820f2
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 01:00:56 2011 -0700
Restore labels on ProxyPair output.
Allow setting the label from the outside.
---
ProxyPair.as | 13 +++++++++----
swfcat.as | 11 +++++++++--
2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/ProxyPair.as b/ProxyPair.as
index ca9f092..62c6ec2 100644
--- a/ProxyPair.as
+++ b/ProxyPair.as
@@ -14,6 +14,9 @@ package
/* An instance of a client-relay connection. */
public class ProxyPair extends EventDispatcher
{
+ // Label for log messages.
+ public var name:String;
+
// Socket to client.
private var s_c:*;
private var connect_c:Function;
@@ -33,13 +36,15 @@ package
public function log(msg:String):void
{
- ui.puts(id() + ": " + msg)
+ if (name)
+ ui.puts(name + ": " + msg)
+ else
+ ui.puts(msg)
}
- // String describing this pair for output.
- public function id():String
+ public function set_name(name:String):void
{
- return "<>";
+ this.name = name;
}
public function ProxyPair(ui:swfcat, s_c:*, connect_c:Function, s_r:*, connect_r:Function)
diff --git a/swfcat.as b/swfcat.as
index 6125187..d9e9bc6 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -265,6 +265,7 @@ package
private function make_proxy_pair(client_spec:String, relay_spec:String):ProxyPair
{
+ var proxy_pair:ProxyPair;
var addr_c:Object;
var addr_r:Object;
var s_c:*;
@@ -278,21 +279,27 @@ package
if (addr_c) {
s_c = new Socket();
s_r = new Socket();
- return new ProxyPair(this, s_c, function ():void {
+ proxy_pair = new ProxyPair(this, s_c, function ():void {
s_c.connect(addr_c.host, addr_c.port);
}, s_r, function ():void {
s_r.connect(addr_r.host, addr_r.port);
});
+ proxy_pair.set_name("<" + addr_c.host + ":" + addr_c.port + ","
+ + addr_r.host + ":" + addr_r.port + ">");
+ return proxy_pair;
}
if (client_spec.match(/^[0-9A-Fa-f]{64}$/)) {
s_c = new RTMFPSocket(CIRRUS_URL, CIRRUS_KEY);
s_r = new Socket();
- return new ProxyPair(this, s_c, function ():void {
+ proxy_pair = new ProxyPair(this, s_c, function ():void {
s_c.connect(client_spec);
}, s_r, function ():void {
s_r.connect(addr_r.host, addr_r.port);
});
+ proxy_pair.set_name("<" + client_spec.substr(0, 4) + "...,"
+ + addr_r.host + ":" + addr_r.port + ">");
+ return proxy_pair;
}
throw new ArgumentError("Can't parse client spec \"" + client_spec + "\".");
1
0
[flashproxy/rtmfp] Do RTMFP client and proxy using the new RTMFPSocket and ProxyPair.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit b631fc0bc82957e07ad2a18ca1747eced2d6ca6e
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 00:25:39 2011 -0700
Do RTMFP client and proxy using the new RTMFPSocket and ProxyPair.
---
swfcat.as | 294 ++++++++++++++++++++++++++++++++++---------------------------
1 files changed, 163 insertions(+), 131 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index ac52ec8..6125187 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -5,26 +5,24 @@ package
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.net.URLRequestMethod;
+ import flash.net.URLVariables;
import flash.events.Event;
+ import flash.events.IOErrorEvent;
+ import flash.events.SecurityErrorEvent;
import flash.utils.setTimeout;
- import FacilitatorSocket;
- import events.FacilitatorSocketEvent;
-
- import ProxyPair;
- import RTMFPProxyPair;
- 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;
+ private const CIRRUS_URL:String = "rtmfp://p2p.rtmfp.net";
+ private const CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;
private const DEFAULT_FACILITATOR_ADDR:Object = {
host: "tor-facilitator.bamsoftware.com",
@@ -47,17 +45,6 @@ package
// Seconds.
private const RATE_LIMIT_HISTORY:Number = 5.0;
- // 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 relay_addr:Object;
-
private var proxy_mode:Boolean;
/* TextField for debug output. */
@@ -124,7 +111,10 @@ package
return;
}
- main();
+ if (proxy_mode)
+ proxy_main();
+ else
+ client_main();
}
/* Get an address structure from the given movie parameter, or the given
@@ -141,129 +131,171 @@ package
}
/* The main logic begins here, after start-up issues are taken care of. */
- private function main():void
+ private function proxy_main():void
{
- if (proxy_mode) {
- establish_facilitator_connection();
- } else {
- establish_cirrus_connection();
+ var fac_url:String;
+ var loader:URLLoader;
+
+ if (num_proxy_pairs >= MAX_NUM_PROXY_PAIRS) {
+ setTimeout(proxy_main, FACILITATOR_POLL_INTERVAL);
+ return;
}
- }
- 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();
- }
- });
- s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
- puts("Error: failed to connect to Cirrus.");
- });
- s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
- puts("Cirrus: closed 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 + ".");
});
- 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 {
- num_proxy_pairs++;
- badge.proxy_begin();
- }
-
- p_p.client = {peer: e.peer, stream: e.stream};
+ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ puts("Facilitator: security error: " + e.text + ".");
});
-
- s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
+
+ fac_url = "http://" + encodeURIComponent(fac_addr.host)
+ + ":" + encodeURIComponent(fac_addr.port) + "/";
+ puts("Facilitator: connecting to " + fac_url + ".");
+ loader.load(new URLRequest(fac_url));
}
- private function establish_facilitator_connection():void
+ private function fac_complete(e:Event):void
{
- 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, FACILITATOR_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, FACILITATOR_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, FACILITATOR_POLL_INTERVAL);
- });
- puts("Facilitator: posting registration.");
- s_f.post_registration(s_c.id);
+ var loader:URLLoader;
+ var client_spec:String;
+ var relay_spec:String;
+ var proxy_pair:Object;
+
+ setTimeout(proxy_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 + "\".");
+
+ try {
+ proxy_pair = make_proxy_pair(client_spec, relay_spec);
+ } catch (e:ArgumentError) {
+ puts("Error: " + e);
+ return;
+ }
+ proxy_pair.addEventListener(Event.COMPLETE, function(e:Event):void {
+ proxy_pair.log("Complete.");
+ num_proxy_pairs--;
+ badge.proxy_end();
+ });
+ proxy_pair.connect();
+
+ num_proxy_pairs++;
+ badge.proxy_begin();
}
-
- private function start_proxy_pair():void
+
+ private function client_main():void
{
- p_p = proxy_pair_factory();
- p_p.addEventListener(Event.CONNECT, function (e:Event):void {
- puts("ProxyPair: connected!");
+ var rs:RTMFPSocket;
+
+ rs = new RTMFPSocket(CIRRUS_URL, CIRRUS_KEY);
+ rs.addEventListener(Event.COMPLETE, function (e:Event):void {
+ puts("Got RTMFP id " + rs.id);
+ register(rs);
});
- p_p.addEventListener(Event.CLOSE, function (e:Event):void {
- puts("ProxyPair: connection closed.");
- p_p = null;
- if (proxy_mode) {
- num_proxy_pairs--;
- badge.proxy_end();
- }
- establish_facilitator_connection();
+ rs.addEventListener(RTMFPSocket.ACCEPT_EVENT, client_accept);
+
+ rs.listen();
+ }
+
+ private function client_accept(e:Event):void {
+ var rs:RTMFPSocket;
+ var s_t:Socket;
+ var proxy_pair:ProxyPair;
+
+ rs = e.target as RTMFPSocket;
+ s_t = new Socket();
+
+ puts("Got RTMFP connection from " + rs.peer_id);
+
+ proxy_pair = new ProxyPair(this, rs, function ():void {
+ /* Do nothing; already connected. */
+ }, s_t, function ():void {
+ s_t.connect(DEFAULT_TOR_CLIENT_ADDR.host, DEFAULT_TOR_CLIENT_ADDR.port);
});
- p_p.relay = relay_addr;
+ proxy_pair.connect();
}
-
- private function rtmfp_proxy_pair_factory():ProxyPair
- {
- return new RTMFPProxyPair(this, s_c, s_c.local_stream_name);
+
+ private function register(rs:RTMFPSocket):void {
+ var fac_url:String;
+ var loader:URLLoader;
+ var request:URLRequest;
+ var variables:URLVariables;
+
+ loader = new URLLoader();
+ loader.addEventListener(Event.COMPLETE, function (e:Event):void {
+ puts("Facilitator: registered.");
+ });
+ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
+ puts("Facilitator: security error: " + e.text + ".");
+ rs.close();
+ });
+ loader.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
+ puts("Facilitator: I/O error: " + e.text + ".");
+ rs.close();
+ });
+
+ fac_url = "http://" + encodeURIComponent(fac_addr.host)
+ + ":" + encodeURIComponent(fac_addr.port) + "/";
+ request = new URLRequest(fac_url);
+ request.method = URLRequestMethod.POST;
+ request.data = new URLVariables;
+ request.data["client"] = rs.id;
+
+ puts("Facilitator: connecting to " + fac_url + ".");
+ loader.load(request);
}
-
- private function tcp_proxy_pair_factory():ProxyPair
+
+ private function make_proxy_pair(client_spec:String, relay_spec:String):ProxyPair
{
- return new TCPProxyPair(this);
+ var addr_c:Object;
+ var addr_r:Object;
+ var s_c:*;
+ var s_r:Socket;
+
+ addr_r = swfcat.parse_addr_spec(relay_spec);
+ if (!addr_r)
+ throw new ArgumentError("Relay spec must be in the form \"host:port\".");
+
+ addr_c = swfcat.parse_addr_spec(client_spec);
+ if (addr_c) {
+ s_c = new Socket();
+ s_r = new Socket();
+ return new ProxyPair(this, s_c, function ():void {
+ s_c.connect(addr_c.host, addr_c.port);
+ }, s_r, function ():void {
+ s_r.connect(addr_r.host, addr_r.port);
+ });
+ }
+
+ if (client_spec.match(/^[0-9A-Fa-f]{64}$/)) {
+ s_c = new RTMFPSocket(CIRRUS_URL, CIRRUS_KEY);
+ s_r = new Socket();
+ return new ProxyPair(this, s_c, function ():void {
+ s_c.connect(client_spec);
+ }, s_r, function ():void {
+ s_r.connect(addr_r.host, addr_r.port);
+ });
+ }
+
+ throw new ArgumentError("Can't parse client spec \"" + client_spec + "\".");
}
/* Parse an address in the form "host:port". Returns an Object with
1
0
[flashproxy/rtmfp] Update documentation for combined TCP/RTMFP proxy.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit f6e2fb73a707c34760326fa760406a38f7144c35
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 01:40:11 2011 -0700
Update documentation for combined TCP/RTMFP proxy.
---
README | 73 +++++++++++++++++++++++++++++++++++++-----------------------
design.txt | 19 +++++++++++----
2 files changed, 59 insertions(+), 33 deletions(-)
diff --git a/README b/README
index ff12174..4b6a2dc 100644
--- a/README
+++ b/README
@@ -16,6 +16,10 @@ There are five main parts. Our terminology for each part is in quotes.
5. A Tor "relay," which is just a normal Tor relay except that its host
must also serve a Flash crossdomain policy.
+A proxy is capable of connecting to a client in two ways: Using a normal
+TCP connection, or over Adobe RTMFP, which involves a third party but is
+capable of traversing NAT.
+
== Demonstration page
https://crypto.stanford.edu/flashproxy/
@@ -28,42 +32,56 @@ Download the (free software) Flex SDK.
http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK
Put its bin directory in your PATH. The important executable is mxmlc.
-You need a Cirrus developer key from Adobe. Put it in the environment
-variable CIRRUS_KEY so it can be found by Makefile.
+For RTMFP support, you need a Cirrus developer key from Adobe. Put it in
+the environment variable CIRRUS_KEY so it can be found by Makefile.
$ export CIRRUS_KEY=XXXXXXXXXXXXXXXXXXXXXXXX-YYYYYYYYYYYY
To build, run
$ make
Copy the resulting swfcat.swf file to a web server.
-On the computer that will be the facilitator, run
+=== Connecting
+
+On the Tor relay, run
sudo ./crossdomaind.py
- ./facilitator.py
-crossdomaind.py needs to be run on any server that will accept
-connections from a Flash proxy. It serves a chunk of data on port 843.
+In general, any computer that a proxy connects to needs to serve a
+crossdomain policy, but the connector and facilitator have it built in.
+
+On the facilitator, run
+ ./facilitator.py -r <relay-ip>
The facilitator runs on port 9002 by default.
+In a browser somewhere, open swfcat.swf and pass it a parameters telling it
+which facilitator to use, for example
+ http://www.example.com/swfcat.swf?facilitator=<facilitator-ip>:9002&debug=1
+
+There are two ways in which the client can receive connections: over TCP
+or RTMFP. TCP doesn't send traffic to anyone other than the facilitator
+and the proxy, but it only works if you have a public IP address. RTMFP
+coordinates connections using a server controlled by Adobe, but works
+when the client is behind a NAT.
+
+To connect with TCP, run
+ ./connector.py -f <facilitator-ip>
+(If you are running the facilitator locally, be sure to use an external
+IP address, not 127.0.0.1.) The connector informs the facilitator that
+it wants a connection, then listens on 0.0.0.0:9000 and 127.0.0.1:9001.
+The proxy will connect on port 9000 and the local Tor will connect on
+9001.
+
+To connect with RTMFP, run
+ ./connector.py 127.0.0.1:9001 127.0.0.1:9002
+and open in a browser
+ http://www.example.com/swfcat.swf?client=1&facilitator=<facilitator-ip>:9002
+In this case, it is swfcat running in client mode that registers with
+the facilitator. The connector acts to join the local swfcat and the
+local Tor client.
+
The client needs to be running a version of Tor that supports the
Socks4Proxy configuration. This means version 0.2.2.1-alpha or
later--not the current stable release.
-On the client, run
- ./connector.py 127.0.0.1:9001 127.0.0.1:9002
-Also on the client, open up the browser to swfcat.swf. Passing no
-arguments should give you good defaults (expects the facilitator running
-on Nate's server). swfcat will connect to the Cirrus server to
-obtain a client ID which it then registers with the facilitator.
-
-In a browser somewhere, open swfcat.swf and pass parameters telling it
-which facilitator to use and to operate in proxy mode.
- http://www.example.com/swfcat.swf?proxy=true&facilitator=<FACILITATOR_IP>:9002&debug=1
-This swfcat will also connect to the Cirrus server to obtain a client ID,
-and then it will ping the facilitator to check if there are any registered
-client IDs. If there is one, it will open a RTMFP connection (coordinated
-by the Cirrus server) to the client and an additional connection to a
-Tor relay.
-
-Back on the client, start Tor with the following configuration:
+Start Tor with the following configuration:
UseBridges 1
Bridge 127.0.0.1:9001
Socks4Proxy 127.0.0.1:9001
@@ -73,8 +91,8 @@ If you see messages like
[notice] no known bridge descriptors running yet; stalling
try deleting the files in ~/.tor or /var/lib/tor.
-You will be able to see byte counts flowing in both browsers displaying
-swfcat.swf (client and proxy), and eventually be able to build a circuit.
+You will be able to see byte counts flowing in the browser window, and
+eventually be able to build a circuit.
== Rationale
@@ -92,16 +110,15 @@ policy.
Clients register with the facilitator by sending an HTTP message:
POST / HTTP/1.0\r\n
\r\n
- client=<CIRRUS-CLIENT-ID>
+ client=<ip-addr/rtmfp-id>
The Flash proxy also gets a client address over HTTP:
GET / HTTP/1.0\r\n
\r\n
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=<CIRRUS-CLIENT-ID>&relay=9.9.9.9:9001
+ client=<ip-addr/rtmfp-id>&relay=<relay-ip>
== ActionScript programming
diff --git a/design.txt b/design.txt
index 27be8ab..2d5ad2b 100644
--- a/design.txt
+++ b/design.txt
@@ -101,13 +101,19 @@ Design of Flash proxies
On startup, the connector sends a registration message to the
facilitator, informing the facilitator that it is waiting for a
connection. The facilitator will later hand this registration to a
- Flash proxy. The registration message is an HTTP POST request of this
+ Flash proxy. The registration message is an HTTP POST request of the
form:
POST / HTTP/1.0
client=[<address>]:<port>
+ or the form:
+
+ POST / HTTP/1.0
+
+ client=[<rtmfp-id>]:<port>
+
The facilitator sends a 200 reply if the registration was successful
and an error status otherwise. If the connector omits the [<address>]
part, the facilitator will automatically fill it in based on the HTTP
@@ -141,11 +147,14 @@ Design of Flash proxies
client=[<address>:<port>]&relay=<address>:<port>
- If <address>:<port> is missing, it means that there are no client
- registrations for this proxy.
+ or this:
+
+ client=[<rtmfp-id>]&relay=<address>:<port>
+
+ If the value for the client parameter is empty, it means that there are no
+ client registrations for this proxy.
- The Flash proxy may serve more than one relay–client pair at once. It
- limits its own bandwidth to 10 KB/s (combined upload/download).
+ The Flash proxy may serve more than one relay–client pair at once.
8. Behavior of the facilitator
1
0
[flashproxy/rtmfp] Show the debug window output always in client mode.
by dcf@torproject.org 12 Jun '11
by dcf@torproject.org 12 Jun '11
12 Jun '11
commit 67ac951f4b75983d1329edab7ab781f0caafd28c
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 01:24:53 2011 -0700
Show the debug window output always in client mode.
---
swfcat.as | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index 27752e9..9739419 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -96,7 +96,7 @@ package
puts("Parameters loaded.");
- if (this.loaderInfo.parameters["debug"])
+ if (this.loaderInfo.parameters["debug"] || this.loaderInfo.parameters["client"])
addChild(output_text);
else
addChild(badge);
1
0
commit 5e8eca1361083409847d4e6c94e5d84adf8d2673
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 01:08:49 2011 -0700
Minor cleanup.
---
swfcat.as | 12 ++++--------
1 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index d9e9bc6..1d99ad4 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -29,8 +29,8 @@ package
port: 9002
};
- /* Default Tor client to use in case of RTMFP connection */
- private const DEFAULT_TOR_CLIENT_ADDR:Object = {
+ /* Local Tor client to use in case of RTMFP connection. */
+ private const LOCAL_TOR_CLIENT_ADDR:Object = {
host: "127.0.0.1",
port: 9002
};
@@ -45,8 +45,6 @@ package
// Seconds.
private const RATE_LIMIT_HISTORY:Number = 5.0;
- private var proxy_mode:Boolean;
-
/* TextField for debug output. */
private var output_text:TextField;
@@ -103,15 +101,13 @@ package
else
addChild(badge);
- proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
-
fac_addr = get_param_addr("facilitator", DEFAULT_FACILITATOR_ADDR);
if (!fac_addr) {
puts("Error: Facilitator spec must be in the form \"host:port\".");
return;
}
- if (proxy_mode)
+ if (this.loaderInfo.parameter["proxy"])
proxy_main();
else
client_main();
@@ -228,7 +224,7 @@ package
proxy_pair = new ProxyPair(this, rs, function ():void {
/* Do nothing; already connected. */
}, s_t, function ():void {
- s_t.connect(DEFAULT_TOR_CLIENT_ADDR.host, DEFAULT_TOR_CLIENT_ADDR.port);
+ s_t.connect(LOCAL_TOR_CLIENT_ADDR.host, LOCAL_TOR_CLIENT_ADDR.port);
});
proxy_pair.connect();
}
1
0
12 Jun '11
commit f0e063240a4c3d673256d82f42fbecd4e35ba1e5
Author: David Fifield <david(a)bamsoftware.com>
Date: Sun Jun 12 01:21:59 2011 -0700
Make proxy mode the default in swfcat.
In other words, use client=true instead of nothing for client mode, and
nothing instead of proxy=true for proxy mode. This makes it a drop-in
replacement for master swfcat.
---
swfcat.as | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/swfcat.as b/swfcat.as
index 1d99ad4..27752e9 100644
--- a/swfcat.as
+++ b/swfcat.as
@@ -107,10 +107,10 @@ package
return;
}
- if (this.loaderInfo.parameter["proxy"])
- proxy_main();
- else
+ if (this.loaderInfo.parameters["client"])
client_main();
+ else
+ proxy_main();
}
/* Get an address structure from the given movie parameter, or the given
1
0
commit 53aecf9837f1dd95d005aaea8a116907488927ea
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jun 11 22:19:30 2011 -0700
Remove unused code.
---
FacilitatorSocket.as | 100 ------------------
RTMFPProxyPair.as | 101 ------------------
TCPProxyPair.as | 77 --------------
events/FacilitatorSocketEvent.as | 24 -----
rtmfp/CirrusSocket.as | 142 --------------------------
rtmfp/RTMFPSocket.as | 202 -------------------------------------
rtmfp/RTMFPSocketClient.as | 46 ---------
rtmfp/events/CirrusSocketEvent.as | 22 ----
rtmfp/events/RTMFPSocketEvent.as | 25 -----
9 files changed, 0 insertions(+), 739 deletions(-)
diff --git a/FacilitatorSocket.as b/FacilitatorSocket.as
deleted file mode 100644
index 70325c1..0000000
--- a/FacilitatorSocket.as
+++ /dev/null
@@ -1,100 +0,0 @@
-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;
- 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;
- loader.load(request);
- }
-
- private function on_complete_event(event:Event):void
- {
- try {
- var client_id:String = event.target.data.client;
- 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, 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_io_error_event(event:IOErrorEvent):void
- {
- fail();
- }
-
- private function on_security_error_event(event:SecurityErrorEvent):void
- {
- fail();
- }
-
- private function get url():String
- {
- return "http://" + encodeURIComponent(host)
- + ":" + encodeURIComponent(port.toString()) + "/";
- }
- }
-}
diff --git a/RTMFPProxyPair.as b/RTMFPProxyPair.as
deleted file mode 100644
index 346d63c..0000000
--- a/RTMFPProxyPair.as
+++ /dev/null
@@ -1,101 +0,0 @@
-package
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.ProgressEvent;
- import flash.net.Socket;
- import flash.utils.ByteArray;
-
- import rtmfp.CirrusSocket;
- import rtmfp.RTMFPSocket;
- import rtmfp.events.RTMFPSocketEvent;
-
- public class RTMFPProxyPair extends ProxyPair
- {
- private var cirrus_socket:CirrusSocket;
- private var client_socket:RTMFPSocket;
- private var listen_stream:String;
-
- public function RTMFPProxyPair(ui:swfcat, cirrus_socket:CirrusSocket, listen_stream:String)
- {
- super(this, ui);
-
- log("Starting RTMFP proxy pair on stream " + listen_stream);
-
- this.cirrus_socket = cirrus_socket;
- this.listen_stream = listen_stream;
-
- setup_client_socket();
- }
-
- override public function set client(client_addr:Object):void
- {
- this.client_addr = client_addr;
- log("Client: connecting to " + client_addr.peer + " on stream " + client_addr.stream + ".");
- client_socket.connect(client_addr.peer, client_addr.stream);
- }
-
- 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;
- RTMFPSocket(src).readBytes(bytes, 0, num_bytes);
- log("RTMFPProxyPair: read " + num_bytes + " bytes from client, writing to relay.");
- Socket(dst).writeBytes(bytes);
- }
-
- if (dst == null) {
- dst = client_socket;
- Socket(src).readBytes(bytes, 0, num_bytes);
- log("RTMFPProxyPair: read " + num_bytes + " bytes from relay, writing to client.");
- RTMFPSocket(dst).writeBytes(bytes);
- }
- }
-
- private function setup_client_socket():void
- {
- client_socket = new RTMFPSocket(cirrus_socket);
- client_socket.addEventListener(RTMFPSocketEvent.CONNECT_FAILED, function (e:RTMFPSocketEvent):void {
- log("Client: connection failed to " + client_addr.peer + " on stream " + client_addr.stream + ".");
- });
- client_socket.addEventListener(RTMFPSocketEvent.CONNECT_SUCCESS, function (e:RTMFPSocketEvent):void {
- log("Client: connected to " + client_addr.peer + " on stream " + client_addr.stream + ".");
- if (connected) {
- dispatchEvent(new Event(Event.CONNECT));
- }
- });
- client_socket.addEventListener(RTMFPSocketEvent.PEER_CONNECTED, function (e:RTMFPSocketEvent):void {
- log("Peer connected.");
- });
- client_socket.addEventListener(RTMFPSocketEvent.PEER_DISCONNECTED, function (e:RTMFPSocketEvent):void {
- log("Client: disconnected from " + client_addr.peer + ".");
- close();
- });
- client_socket.addEventListener(RTMFPSocketEvent.PLAY_STARTED, function (e:RTMFPSocketEvent):void {
- log("Play started.");
- });
- client_socket.addEventListener(RTMFPSocketEvent.PUBLISH_STARTED, function (e:RTMFPSocketEvent):void {
- log("Publishing started.");
- });
- client_socket.addEventListener(ProgressEvent.SOCKET_DATA, client_to_relay);
-
- client_socket.listen(listen_stream);
- }
- }
-}
\ No newline at end of file
diff --git a/TCPProxyPair.as b/TCPProxyPair.as
deleted file mode 100644
index de18dd6..0000000
--- a/TCPProxyPair.as
+++ /dev/null
@@ -1,77 +0,0 @@
-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, 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 --git a/events/FacilitatorSocketEvent.as b/events/FacilitatorSocketEvent.as
deleted file mode 100644
index 5787309..0000000
--- a/events/FacilitatorSocketEvent.as
+++ /dev/null
@@ -1,24 +0,0 @@
-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, relay:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- this.client = client;
- this.relay = relay;
- }
- }
-}
diff --git a/rtmfp/CirrusSocket.as b/rtmfp/CirrusSocket.as
deleted file mode 100644
index 071ac0d..0000000
--- a/rtmfp/CirrusSocket.as
+++ /dev/null
@@ -1,142 +0,0 @@
-/* CirrusSocket abstraction
- * ------------------------
- * Manages the NetConnection portion of RTMFP and also handles
- * the handshake between two Flash players to decide what their
- * data stream names will be.
- *
- * TODO: consider using farNonce/nearNonce instead of sending bytes?
- */
-
-package rtmfp
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.IOErrorEvent;
- import flash.events.NetStatusEvent;
- import flash.events.ProgressEvent;
- import flash.events.SecurityErrorEvent;
- import flash.net.NetConnection;
- import flash.utils.clearInterval;
- import flash.utils.setInterval;
-
- import rtmfp.RTMFPSocket;
- import rtmfp.events.CirrusSocketEvent;
- import rtmfp.events.RTMFPSocketEvent;
-
- [Event(name=CirrusSocketEvent.CONNECT_CLOSED, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- [Event(name=CirrusSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- [Event(name=CirrusSocketEvent.CONNECT_SUCCESS, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- [Event(name=CirrusSocketEvent.HELLO_RECEIVED, type="com.flashproxy.rtmfp.events.CirrusSocketEvent")]
- public class CirrusSocket extends EventDispatcher
- {
- private static const CONNECT_TIMEOUT:uint = 4000; // in milliseconds
-
- /* We'll append a unique number to the DATA_STREAM_PREFIX for each
- new stream we create so that we have unique streams per player. */
- private static const DATA_STREAM_PREFIX:String = "DATA";
- private var data_stream_suffix:uint = 0;
-
- /* Connection to the Cirrus rendezvous service */
- public var connection:NetConnection;
-
- /* Timeouts */
- private var connect_timeout:int;
- private var hello_timeout:int;
-
- public function CirrusSocket()
- {
- connection = new NetConnection();
- connection.addEventListener(NetStatusEvent.NET_STATUS, on_net_status_event);
- connection.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event);
- connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event);
-
- /* Set up a client object to handle the hello callback */
- var client:Object = new Object();
- client.onRelay = on_hello;
- connection.client = client;
- }
-
- public function connect(addr:String, key:String):void
- {
- if (!this.connected) {
- connect_timeout = setInterval(fail, CONNECT_TIMEOUT);
- connection.connect(addr, key);
- } else {
- throw new Error("Cannot connect Cirrus socket: already connected.");
- }
- }
-
- public function close():void
- {
- if (this.connected) {
- connection.close();
- } else {
- throw new Error("Cannot close Cirrus socket: not connected.");
- }
- }
-
- public function get connected():Boolean
- {
- return (connection != null && connection.connected);
- }
-
- public function get id():String
- {
- if (this.connected) {
- return connection.nearID;
- }
-
- return null;
- }
-
- public function get local_stream_name():String
- {
- return DATA_STREAM_PREFIX + data_stream_suffix;
- }
-
- /* Sends a hello message to the Flash player with Cirrus ID "id"
- We use this new call protocol outlined here:
- http://forums.adobe.com/thread/780788?tstart=0 */
- public function send_hello(id:String):void
- {
- if (this.connected) {
- connection.call("relay", null, id, local_stream_name);
- } else {
- throw new Error("Cannot send hello: Cirrus socket not connected.");
- }
- }
-
-/*************************** PRIVATE HELPER FUNCTIONS *************************/
-
- private function fail():void
- {
- clearInterval(connect_timeout);
- dispatchEvent(new CirrusSocketEvent(CirrusSocketEvent.CONNECT_FAILED));
- }
-
- private function on_hello(peer:String, ...args):void
- {
- var stream:String = args[0];
- dispatchEvent(new CirrusSocketEvent(CirrusSocketEvent.HELLO_RECEIVED, peer, stream));
- data_stream_suffix++;
- }
-
- private function on_io_error_event(event:IOErrorEvent):void
- {
- fail();
- }
-
- private function on_net_status_event(event:NetStatusEvent):void
- {
- if (event.info.code == "NetConnection.Connect.Success") {
- clearInterval(connect_timeout);
- dispatchEvent(new CirrusSocketEvent(CirrusSocketEvent.CONNECT_SUCCESS));
- }
- }
-
- private function on_security_error_event(event:SecurityErrorEvent):void
- {
- fail();
- }
- }
-}
diff --git a/rtmfp/RTMFPSocket.as b/rtmfp/RTMFPSocket.as
deleted file mode 100644
index 4efe702..0000000
--- a/rtmfp/RTMFPSocket.as
+++ /dev/null
@@ -1,202 +0,0 @@
-package rtmfp
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.IOErrorEvent;
- import flash.events.NetStatusEvent;
- import flash.events.ProgressEvent;
- import flash.events.SecurityErrorEvent;
- import flash.net.NetConnection;
- import flash.net.NetStream;
- import flash.utils.ByteArray;
- import flash.utils.clearTimeout;
- import flash.utils.setTimeout;
-
- import rtmfp.CirrusSocket;
- import rtmfp.RTMFPSocketClient;
- import rtmfp.events.CirrusSocketEvent;
- import rtmfp.events.RTMFPSocketEvent;
-
- [Event(name=RTMFPSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.CONNECT_CLOSED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.CONNECT_SUCCESS, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PEER_CONNECTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PEER_DISCONNECTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PLAY_STARTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PUBLISH_STARTED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- [Event(name=RTMFPSocketEvent.PUBLISH_FAILED, type="com.flashproxy.rtmfp.events.RTMFPSocketEvent")]
- public class RTMFPSocket extends EventDispatcher
- {
- private const CONNECT_TIMEOUT:uint = 10000;
-
- private var s_c:CirrusSocket;
-
- private var recv_stream:NetStream;
- private var send_stream:NetStream;
-
- private var peer_stream:NetStream;
-
- private var connect_timeout:int;
-
- public function RTMFPSocket(s_c:CirrusSocket)
- {
- this.s_c = s_c;
- recv_stream = null;
- send_stream = null;
- connect_timeout = 0;
- }
-
- /* Tears down this RTMFPSocket, closing both its streams.
- To be used when destroying this object. */
- public function close():void
- {
- if (send_stream != null) {
- s_c.connection.removeEventListener(NetStatusEvent.NET_STATUS, on_stream_disconnection_event);
- send_stream.close();
- }
-
- if (recv_stream != null) {
- recv_stream.close();
- }
- }
-
- /* In RTMFP, you connect to a remote socket by requesting to
- "play" the data being published on a named stream by the
- host identified by id. The connection request goes through
- the Cirrus server which handles the mapping from id/stream
- to IP/port and any necessary NAT traversal. */
- public function connect(id:String, stream:String):void
- {
- recv_stream = new NetStream(s_c.connection, id);
- var client:RTMFPSocketClient = new RTMFPSocketClient();
- client.addEventListener(ProgressEvent.SOCKET_DATA, on_data_available, false, 0, true);
- client.addEventListener(RTMFPSocketClient.CONNECT_ACKNOWLEDGED, on_connect_acknowledged, false, 0, true);
- recv_stream.client = client;
- recv_stream.addEventListener(NetStatusEvent.NET_STATUS, on_recv_stream_event);
- recv_stream.play(stream);
- connect_timeout = setTimeout(on_connect_timeout, CONNECT_TIMEOUT, recv_stream);
- }
-
- public function get connected():Boolean
- {
- return (recv_stream != null && recv_stream.client != null &&
- RTMFPSocketClient(recv_stream.client).connect_acknowledged);
- }
-
- /* In RTMFP, you open a listening socket by publishing a named
- stream that others can connect to instead of listening on a port.
- You register this stream with the Cirrus server via the Cirrus
- socket so that it can redirect connection requests for an id/stream
- tuple to this socket. */
- public function listen(stream:String):void
- {
- // apparently streams don't get disconnection events, only the NetConnection
- // object does...bleh.
- s_c.connection.addEventListener(NetStatusEvent.NET_STATUS, on_stream_disconnection_event);
-
- send_stream = new NetStream(s_c.connection, NetStream.DIRECT_CONNECTIONS);
- send_stream.addEventListener(NetStatusEvent.NET_STATUS, on_send_stream_event);
- var client:Object = new Object();
- client.onPeerConnect = on_peer_connect;
- send_stream.client = client;
- send_stream.publish(stream);
- }
-
- public function get peer():String
- {
- if (!connected) return null;
- return recv_stream.farID;
- }
-
- public function get peer_connected():Boolean
- {
- return send_stream.peerStreams.length > 0;
- }
-
- public function readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void
- {
- if (recv_stream != null && recv_stream.client != null) {
- recv_stream.client.bytes.readBytes(bytes, offset, length);
- }
- }
-
- public function writeBytes(bytes:ByteArray):void
- {
- if (send_stream != null && peer_connected) {
- send_stream.send(RTMFPSocketClient.DATA_AVAILABLE, bytes);
- }
- }
-
- /* Listens for acknowledgement of a connection attempt to a
- remote peer. */
- private function on_connect_acknowledged(event:Event):void
- {
- clearTimeout(connect_timeout);
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_SUCCESS, recv_stream));
- }
-
- /* If we don't get a connection acknowledgement by the time this
- timeout function is called, we punt. */
- private function on_connect_timeout(peer:NetStream):void
- {
- if (!this.connected) {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.CONNECT_FAILED, recv_stream));
- }
- }
-
- private function on_data_available(event:ProgressEvent):void
- {
- dispatchEvent(event);
- }
-
- private function on_recv_stream_event(event:NetStatusEvent):void
- {
- /* empty, here for symmetry */
- }
-
- /* This function gets called whenever someone tries to connect
- to this socket's send_stream tuple. We don't want multiple
- peers connecting at once, so we disallow that. The socket
- acknowledges the connection back to the peer with the
- SET_CONNECTION_ACKNOWLEDGED message. */
- private function on_peer_connect(peer:NetStream):Boolean
- {
- if (peer_connected) {
- return false;
- }
-
- peer_stream = peer;
- peer.send(RTMFPSocketClient.SET_CONNECT_ACKNOWLEDGED);
-
- // need to do this in a timeout so that this function can
- // return true to finalize the connection before firing the event
- setTimeout(function (stream:NetStream):void {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_CONNECTED, stream));
- }, 0, peer);
-
- return true;
- }
-
- private function on_send_stream_event(event:NetStatusEvent):void
- {
- switch (event.info.code) {
- case "NetStream.Publish.Start":
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PUBLISH_STARTED));
- break;
- case "NetStream.Publish.BadName":
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PUBLISH_FAILED));
- break;
- default:
- break;
- }
- }
-
- private function on_stream_disconnection_event(event:NetStatusEvent):void
- {
- if (event.info.code == "NetStream.Connect.Closed" && event.info.stream === peer_stream) {
- dispatchEvent(new RTMFPSocketEvent(RTMFPSocketEvent.PEER_DISCONNECTED));
- }
- }
- }
-}
-
diff --git a/rtmfp/RTMFPSocketClient.as b/rtmfp/RTMFPSocketClient.as
deleted file mode 100644
index b917bcb..0000000
--- a/rtmfp/RTMFPSocketClient.as
+++ /dev/null
@@ -1,46 +0,0 @@
-package rtmfp
-{
- import flash.events.Event;
- import flash.events.EventDispatcher;
- import flash.events.ProgressEvent;
- import flash.utils.ByteArray;
-
- [Event(name=RTMFPSocketClient.CONNECT_ACKNOWLEDGED, type="flash.events.Event")]
- public dynamic class RTMFPSocketClient extends EventDispatcher {
- public static const DATA_AVAILABLE:String = "data_available";
- public static const CONNECT_ACKNOWLEDGED:String = "connectAcknowledged";
- public static const SET_CONNECT_ACKNOWLEDGED:String = "set_connect_acknowledged";
-
- private var _bytes:ByteArray;
- private var _connect_acknowledged:Boolean;
-
- public function RTMFPSocketClient()
- {
- super();
- _bytes = new ByteArray();
- _connect_acknowledged = false;
- }
-
- public function get bytes():ByteArray
- {
- return _bytes;
- }
-
- public function data_available(bytes:ByteArray):void
- {
- bytes.readBytes(_bytes, _bytes.length, 0);
- dispatchEvent(new ProgressEvent(ProgressEvent.SOCKET_DATA, false, false, _bytes.bytesAvailable, _bytes.bytesAvailable));
- }
-
- public function get connect_acknowledged():Boolean
- {
- return _connect_acknowledged;
- }
-
- public function set_connect_acknowledged():void
- {
- _connect_acknowledged = true;
- dispatchEvent(new Event(CONNECT_ACKNOWLEDGED));
- }
- }
-}
diff --git a/rtmfp/events/CirrusSocketEvent.as b/rtmfp/events/CirrusSocketEvent.as
deleted file mode 100644
index 831ad73..0000000
--- a/rtmfp/events/CirrusSocketEvent.as
+++ /dev/null
@@ -1,22 +0,0 @@
-package rtmfp.events
-{
- import flash.events.Event;
-
- public class CirrusSocketEvent 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 HELLO_RECEIVED:String = "helloReceived";
-
- public var peer:String;
- public var stream:String;
-
- public function CirrusSocketEvent(type:String, peer:String = null, stream:String = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- this.peer = peer;
- this.stream = stream;
- }
- }
-}
diff --git a/rtmfp/events/RTMFPSocketEvent.as b/rtmfp/events/RTMFPSocketEvent.as
deleted file mode 100644
index 87a7e09..0000000
--- a/rtmfp/events/RTMFPSocketEvent.as
+++ /dev/null
@@ -1,25 +0,0 @@
-package rtmfp.events
-{
- import flash.events.Event;
- import flash.net.NetStream;
-
- public class RTMFPSocketEvent extends Event
- {
- public static const CONNECT_FAILED:String = "connectFailed";
- public static const CONNECT_SUCCESS:String = "connectSuccess";
- public static const CONNECT_CLOSED:String = "connectClosed"
- public static const PEER_CONNECTED:String = "peerConnected";
- public static const PEER_DISCONNECTED:String = "peerDisconnected";
- public static const PLAY_STARTED:String = "playStarted";
- public static const PUBLISH_STARTED:String = "publishStarted";
- public static const PUBLISH_FAILED:String = "publishFailed";
-
- public var stream:NetStream;
-
- public function RTMFPSocketEvent(type:String, stream:NetStream = null, bubbles:Boolean = false, cancelable:Boolean = false)
- {
- super(type, bubbles, cancelable);
- this.stream = stream;
- }
- }
-}
1
0