commit ea1618074e82e45542fbf2be79334b2517eadbd5
Author: David Fifield <david(a)bamsoftware.com>
Date: Sat Jul 23 04:44:12 2011 +0000
Allow relaying data while one end of a ProxyPair is disconnected.
Data could be left stranded when one end became closed after data had
been read but before it had been flushed to the other side.
---
ProxyPair.as | 49 +++++++++++++++++++++++++++++++++++++++----------
1 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/ProxyPair.as b/ProxyPair.as
index 10c4263..237ab69 100644
--- a/ProxyPair.as
+++ b/ProxyPair.as
@@ -86,13 +86,13 @@ package
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(Event.CLOSE, relay_closed);
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(Event.CLOSE, client_closed);
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);
@@ -113,6 +113,18 @@ package
log("Client: connected.");
}
+ private function relay_closed(e:Event):void
+ {
+ log("Relay: closed.");
+ flush();
+ }
+
+ private function client_closed(e:Event):void
+ {
+ log("Client: closed.");
+ flush();
+ }
+
private function relay_to_client(e:ProgressEvent):void
{
r2c_schedule.push(e.bytesLoaded);
@@ -141,24 +153,41 @@ package
/* Send as much data as the rate limit currently allows. */
private function flush():void
{
+ var busy:Boolean;
+
if (flush_id)
clearTimeout(flush_id);
flush_id = undefined;
- if (!(s_r.connected && s_c.connected))
- /* Can't do anything until both sockets are connected. */
+ if (!s_r.connected && !s_c.connected)
+ /* Can't do anything while both sockets are disconnected. */
return;
- while (!ui.rate_limit.is_limited() &&
- (r2c_schedule.length > 0 || c2r_schedule.length > 0)) {
- if (r2c_schedule.length > 0)
+ busy = true;
+ while (busy && !ui.rate_limit.is_limited()) {
+ busy = false;
+ if (s_c.connected && r2c_schedule.length > 0) {
transfer_chunk(s_r, s_c, r2c_schedule.shift(), "Relay");
- if (c2r_schedule.length > 0)
+ busy = true;
+ }
+ if (s_r.connected && c2r_schedule.length > 0) {
transfer_chunk(s_c, s_r, c2r_schedule.shift(), "Client");
+ busy = true;
+ }
+ }
+
+ if (!s_r.connected && r2c_schedule.length == 0) {
+ log("Client: closing.");
+ s_c.close();
+ }
+ if (!s_c.connected && c2r_schedule.length == 0) {
+ log("Relay: closing.");
+ s_r.close();
}
- /* Call again when safe, if necessary. */
- if (r2c_schedule.length > 0 || c2r_schedule.length > 0)
+ if (!s_c.connected && !s_r.connected)
+ dispatchEvent(new Event(Event.COMPLETE));
+ else if (r2c_schedule.length > 0 || c2r_schedule.length > 0)
flush_id = setTimeout(flush, ui.rate_limit.when() * 1000);
}
}