From 5663a717df8dff02f17a9813829fb8f23d338904 Mon Sep 17 00:00:00 2001
From: Tao Wang <t55wang@uwaterloo.ca>
Date: Tue, 2 Apr 2013 15:56:49 -0700
Subject: [PATCH 27/41] Use Optimistic Data SOCKS variant.

This patch alters Firefox's SOCKS handshake to preemptively send data before
it is actually connected. This allows us to save a round trip during
connection setup.

See:
https://gitweb.torproject.org/torspec.git/blob/HEAD:/proposals/181-optimistic-data-client.txt
---
 netwerk/base/src/nsSocketTransport2.cpp | 20 ++++++++++++++++++--
 netwerk/base/src/nsSocketTransport2.h   |  4 +++-
 netwerk/socket/nsSOCKSIOLayer.cpp       |  4 +++-
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp
index 15870bb..668d18f 100644
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -1543,9 +1543,25 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
         // Update poll timeout in case it was changed
         mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
     }
-    else if (mState == STATE_CONNECTING) {
+
+//STATE_SENDINGGET: handshake proceeded to state "sent connect"
+//one more poll to OnSocketReady will trigger the get request, and state STATE_SENTGET
+//STATE_SENTGET: continue and finish handshake
+    else if (mState == STATE_SENDINGGET) {
+        if ((mPollFlags & PR_POLL_WRITE) && (outFlags & ~PR_POLL_READ)) {
+            mOutput.OnSocketReady(NS_OK);
+        }
+        mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
+        mState = STATE_SENTGET;
+    }
+
+    else if (mState == STATE_CONNECTING || mState == STATE_SENTGET) {
         PRStatus status = PR_ConnectContinue(fd, outFlags);
-        if (status == PR_SUCCESS) {
+        if (status == PR_SUCCESS && mState == STATE_CONNECTING) {
+            OnSocketConnected();
+            mState = STATE_SENDINGGET;
+        }
+        else if (status == PR_SUCCESS && mState == STATE_SENTGET) {
             //
             // we are connected!
             //
diff --git a/netwerk/base/src/nsSocketTransport2.h b/netwerk/base/src/nsSocketTransport2.h
index d9ac3d3..0c92d0a 100644
--- a/netwerk/base/src/nsSocketTransport2.h
+++ b/netwerk/base/src/nsSocketTransport2.h
@@ -154,7 +154,9 @@ private:
         STATE_IDLE,
         STATE_RESOLVING,
         STATE_CONNECTING,
-        STATE_TRANSFERRING
+        STATE_TRANSFERRING,
+        STATE_SENDINGGET,
+        STATE_SENTGET
     };
 
     //-------------------------------------------------------------------------
diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp
index 24edc78..64f6001 100644
--- a/netwerk/socket/nsSOCKSIOLayer.cpp
+++ b/netwerk/socket/nsSOCKSIOLayer.cpp
@@ -77,7 +77,9 @@ public:
     void SetConnectTimeout(PRIntervalTime to);
     PRStatus DoHandshake(PRFileDesc *fd, int16_t oflags = -1);
     int16_t GetPollFlags() const;
-    bool IsConnected() const { return mState == SOCKS_CONNECTED; }
+    bool IsConnected() const { return (mState == SOCKS_CONNECTED ||
+                                       mState == SOCKS5_READ_CONNECT_RESPONSE_TOP); }
+ 
     void ForgetFD() { mFD = nullptr; }
 
 private:
-- 
1.8.1.2

