Bug 1390881 - Check whether TFO cookie or TFO cookie and data are sent on Windows. r=mcmanus
authorDragana Damjanovic <dd.mozilla@gmail.com>
Sun, 20 Aug 2017 09:45:17 +0200
changeset 649614 77117a16d3c37455dec09710661ef493e231a6bc
parent 649613 71f4f2c0ec56937235b27ebbc3089af63991d1d0
child 649615 29b8fd865a473cc4783bcd455b2d373d273d0363
push id75073
push userbmo:mozilla@hocat.ca
push dateSun, 20 Aug 2017 22:21:51 +0000
reviewersmcmanus
bugs1390881
milestone57.0a1
Bug 1390881 - Check whether TFO cookie or TFO cookie and data are sent on Windows. r=mcmanus
netwerk/base/nsSocketTransport2.cpp
netwerk/base/nsSocketTransport2.h
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -795,16 +795,17 @@ nsSocketTransport::nsSocketTransport()
     , mOutput(this)
     , mQoSBits(0x00)
     , mKeepaliveEnabled(false)
     , mKeepaliveIdleTimeS(-1)
     , mKeepaliveRetryIntervalS(-1)
     , mKeepaliveProbeCount(-1)
     , mFastOpenCallback(nullptr)
     , mFastOpenLayerHasBufferedData(false)
+    , mFastOpenStatus(TFO_NOT_TRIED)
     , mDoNotRetryToConnect(false)
 {
     SOCKET_LOG(("creating nsSocketTransport @%p\n", this));
 
     mTimeouts[TIMEOUT_CONNECT]    = UINT16_MAX; // no timeout
     mTimeouts[TIMEOUT_READ_WRITE] = UINT16_MAX; // no timeout
 }
 
@@ -1565,35 +1566,34 @@ nsSocketTransport::InitiateSocket()
             mFastOpenCallback = nullptr;
             MutexAutoLock lock(mLock);
             mFDFastOpenInProgress = false;
             return rv;
         }
         status = PR_FAILURE;
         connectCalled = false;
         bool fastOpenNotSupported = false;
-        uint8_t tfoStatus = TFO_NOT_TRIED;
-        TCPFastOpenFinish(fd, code, fastOpenNotSupported, tfoStatus);
+        TCPFastOpenFinish(fd, code, fastOpenNotSupported, mFastOpenStatus);
 
         // If we have sent data, trigger a socket status event.
-        if (tfoStatus == TFO_DATA_SENT) {
+        if (mFastOpenStatus == TFO_DATA_SENT) {
             SendStatus(NS_NET_STATUS_SENDING_TO);
         }
 
         // If we have still some data buffered this data must be flush before
         // mOutput.OnSocketReady(NS_OK) is called in
         // nsSocketTransport::OnSocketReady, partially to keep socket status
         // event in order.
         mFastOpenLayerHasBufferedData = TCPFastOpenGetCurrentBufferSize(fd);
 
-        mFastOpenCallback->SetFastOpenStatus(tfoStatus);
+        mFastOpenCallback->SetFastOpenStatus(mFastOpenStatus);
         SOCKET_LOG(("called StartFastOpen - code=%d; fastOpen is %s "
                     "supported.\n", code,
                     fastOpenNotSupported ? "not" : ""));
-        SOCKET_LOG(("TFO status %d\n", tfoStatus));
+        SOCKET_LOG(("TFO status %d\n", mFastOpenStatus));
 
         if (fastOpenNotSupported) {
           // When TCP_FastOpen is turned off on the local host
           // SendTo will return PR_NOT_TCP_SOCKET_ERROR. This is only
           // on Linux.
           // If a windows version does not support Fast Open, the return value
           // will be PR_NOT_IMPLEMENTED_ERROR. This is only for windows 10
           // versions older than version 1607, because we do not have subverion
@@ -2212,16 +2212,34 @@ nsSocketTransport::OnSocketReady(PRFileD
         // nsIOService::LastConectivityChange time to be atomic.
         PRIntervalTime connectStarted = 0;
         if (gSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
             connectStarted = PR_IntervalNow();
         }
 
         PRStatus status = PR_ConnectContinue(fd, outFlags);
 
+#if defined(_WIN64) && defined(WIN95)
+#ifndef TCP_FASTOPEN
+#define TCP_FASTOPEN 15
+#endif
+
+        if (mFDFastOpenInProgress && mFastOpenCallback &&
+            (mFastOpenStatus == TFO_DATA_SENT)) {
+            PROsfd osfd = PR_FileDesc2NativeHandle(fd);
+            BOOL option = 0;
+            int len = sizeof(option);
+            PRInt32 rv = getsockopt((SOCKET)osfd, IPPROTO_TCP, TCP_FASTOPEN, (char*)&option, &len);
+            if ((rv != 0) && !option) {
+                // On error, I will let the normal necko paths pickup the error.
+                mFastOpenCallback->SetFastOpenStatus(TFO_NOT_TRIED);
+            }
+        }
+#endif
+
         if (gSocketTransportService->IsTelemetryEnabledAndNotSleepPhase() &&
             connectStarted) {
             SendPRBlockingTelemetry(connectStarted,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_NORMAL,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_SHUTDOWN,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_CONNECTIVITY_CHANGE,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_LINK_CHANGE,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_OFFLINE);
--- a/netwerk/base/nsSocketTransport2.h
+++ b/netwerk/base/nsSocketTransport2.h
@@ -473,16 +473,17 @@ private:
     // Keepalive config (support varies by platform).
     int32_t mKeepaliveIdleTimeS;
     int32_t mKeepaliveRetryIntervalS;
     int32_t mKeepaliveProbeCount;
 
     // A Fast Open callback.
     TCPFastOpen *mFastOpenCallback;
     bool mFastOpenLayerHasBufferedData;
+    uint8_t mFastOpenStatus;
 
     bool mDoNotRetryToConnect;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // !nsSocketTransport_h__