Title: [263879] trunk
Revision
263879
Author
commit-qu...@webkit.org
Date
2020-07-02 19:01:21 -0700 (Thu, 02 Jul 2020)

Log Message

Add testing infrastructure and SPI declaration for HTTP/2 ping
https://bugs.webkit.org/show_bug.cgi?id=213913

Patch by Alex Christensen <achristen...@webkit.org> on 2020-07-02
Reviewed by Jer Noble.

Source/WebCore/PAL:

* pal/spi/cf/CFNetworkSPI.h:

Source/WTF:

This is work towards rdar://problem/64495827

* wtf/PlatformHave.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm:
(-[SessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
(TestWebKitAPI::pingPong):
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/HTTPServer.h:
(TestWebKitAPI::H2::Frame::Frame):
(TestWebKitAPI::H2::Frame::type const):
(TestWebKitAPI::H2::Frame::flags const):
(TestWebKitAPI::H2::Frame::streamID const):
(TestWebKitAPI::H2::Frame::payload const):
(TestWebKitAPI::H2::Connection::create):
(TestWebKitAPI::H2::Connection::Connection):
* TestWebKitAPI/cocoa/HTTPServer.mm:
(TestWebKitAPI::HTTPServer::listenerParameters):
(TestWebKitAPI::dataFromVector):
(TestWebKitAPI::vectorFromData):
(TestWebKitAPI::HTTPServer::request const):
(TestWebKitAPI::Connection::receiveBytes const):
(TestWebKitAPI::Connection::receiveHTTPRequest const):
(TestWebKitAPI::Connection::send const):
(TestWebKitAPI::H2::Connection::send const):
(TestWebKitAPI::H2::Connection::receive const):

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (263878 => 263879)


--- trunk/Source/WTF/ChangeLog	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Source/WTF/ChangeLog	2020-07-03 02:01:21 UTC (rev 263879)
@@ -1,3 +1,14 @@
+2020-07-02  Alex Christensen  <achristen...@webkit.org>
+
+        Add testing infrastructure and SPI declaration for HTTP/2 ping
+        https://bugs.webkit.org/show_bug.cgi?id=213913
+
+        Reviewed by Jer Noble.
+
+        This is work towards rdar://problem/64495827
+
+        * wtf/PlatformHave.h:
+
 2020-07-01  Tim Horton  <timothy_hor...@apple.com>
 
         Upstream application accent color support

Modified: trunk/Source/WTF/wtf/PlatformHave.h (263878 => 263879)


--- trunk/Source/WTF/wtf/PlatformHave.h	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Source/WTF/wtf/PlatformHave.h	2020-07-03 02:01:21 UTC (rev 263879)
@@ -380,6 +380,14 @@
 #define HAVE_ACCESSIBILITY_BUNDLES_PATH 1
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101600) \
+    || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 140000) \
+    || (PLATFORM(WATCHOS) && __WATCH_OS_VERSION_MIN_REQUIRED >= 70000) \
+    || (PLATFORM(APPLETV) && __TV_OS_VERSION_MIN_REQUIRED >= 140000) \
+    || (PLATFORM(MACCATALYST) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 140000)
+#define HAVE_PRECONNECT_PING 1
+#endif
+
 #if PLATFORM(COCOA) && !(PLATFORM(MAC) && !(__MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101404))
 #define HAVE_CFNETWORK_OVERRIDE_SESSION_COOKIE_ACCEPT_POLICY 1
 #endif

Modified: trunk/Source/WebCore/PAL/ChangeLog (263878 => 263879)


--- trunk/Source/WebCore/PAL/ChangeLog	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Source/WebCore/PAL/ChangeLog	2020-07-03 02:01:21 UTC (rev 263879)
@@ -1,3 +1,12 @@
+2020-07-02  Alex Christensen  <achristen...@webkit.org>
+
+        Add testing infrastructure and SPI declaration for HTTP/2 ping
+        https://bugs.webkit.org/show_bug.cgi?id=213913
+
+        Reviewed by Jer Noble.
+
+        * pal/spi/cf/CFNetworkSPI.h:
+
 2020-07-01  Tim Horton  <timothy_hor...@apple.com>
 
         Upstream application accent color support

Modified: trunk/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h (263878 => 263879)


--- trunk/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h	2020-07-03 02:01:21 UTC (rev 263879)
@@ -67,6 +67,17 @@
 
 #else // !PLATFORM(WIN) && !USE(APPLE_INTERNAL_SDK)
 
+#if HAVE(PRECONNECT_PING)
+@interface _NSHTTPConnectionInfo : NSObject
+- (void)sendPingWithReceiveHandler:(void (^)(NSError * _Nullable error, NSTimeInterval interval))pongHandler;
+@property (readonly) BOOL isValid;
+@end
+
+@interface NSURLSessionTask (HTTPConnectionInfo)
+- (void)getUnderlyingHTTPConnectionInfoWithCompletionHandler:(void (^)(_NSHTTPConnectionInfo *connectionInfo))completionHandler;
+@end
+#endif // HAVE(PRECONNECT_PING)
+
 #if HAVE(LOGGING_PRIVACY_LEVEL)
 typedef enum {
     nw_context_privacy_level_public = 1,

Modified: trunk/Tools/ChangeLog (263878 => 263879)


--- trunk/Tools/ChangeLog	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Tools/ChangeLog	2020-07-03 02:01:21 UTC (rev 263879)
@@ -1,3 +1,33 @@
+2020-07-02  Alex Christensen  <achristen...@webkit.org>
+
+        Add testing infrastructure and SPI declaration for HTTP/2 ping
+        https://bugs.webkit.org/show_bug.cgi?id=213913
+
+        Reviewed by Jer Noble.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm:
+        (-[SessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
+        (TestWebKitAPI::pingPong):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/cocoa/HTTPServer.h:
+        (TestWebKitAPI::H2::Frame::Frame):
+        (TestWebKitAPI::H2::Frame::type const):
+        (TestWebKitAPI::H2::Frame::flags const):
+        (TestWebKitAPI::H2::Frame::streamID const):
+        (TestWebKitAPI::H2::Frame::payload const):
+        (TestWebKitAPI::H2::Connection::create):
+        (TestWebKitAPI::H2::Connection::Connection):
+        * TestWebKitAPI/cocoa/HTTPServer.mm:
+        (TestWebKitAPI::HTTPServer::listenerParameters):
+        (TestWebKitAPI::dataFromVector):
+        (TestWebKitAPI::vectorFromData):
+        (TestWebKitAPI::HTTPServer::request const):
+        (TestWebKitAPI::Connection::receiveBytes const):
+        (TestWebKitAPI::Connection::receiveHTTPRequest const):
+        (TestWebKitAPI::Connection::send const):
+        (TestWebKitAPI::H2::Connection::send const):
+        (TestWebKitAPI::H2::Connection::receive const):
+
 2020-07-02  Kate Cheney  <katherine_che...@apple.com>
 
         Custom URL schemes should be treated as app-bound

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm (263878 => 263879)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm	2020-07-03 02:01:21 UTC (rev 263879)
@@ -32,8 +32,21 @@
 #import "TestNavigationDelegate.h"
 #import "Utilities.h"
 #import <WebKit/WKWebViewPrivate.h>
+#import <pal/spi/cf/CFNetworkSPI.h>
 #import <wtf/RetainPtr.h>
 
+#if HAVE(PRECONNECT_PING)
+@interface SessionDelegate : NSObject <NSURLSessionDataDelegate>
+@end
+
+@implementation SessionDelegate
+- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
+{
+    completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
+}
+@end
+#endif
+
 namespace TestWebKitAPI {
 
 TEST(Preconnect, HTTP)
@@ -90,6 +103,76 @@
 
 #endif
 
+#if HAVE(PRECONNECT_PING)
+static void pingPong(Ref<H2::Connection>&& connection, size_t* headersCount)
+{
+    connection->receive([connection, headersCount] (H2::Frame&& frame) mutable {
+        switch (frame.type()) {
+        case H2::Frame::Type::Headers:
+            ++*headersCount;
+            break;
+        case H2::Frame::Type::Settings:
+        case H2::Frame::Type::WindowUpdate:
+            // These frame types are ok for a preconnect task.
+            break;
+        case H2::Frame::Type::Ping:
+            {
+                // https://http2.github.io/http2-spec/#rfc.section.6.7
+                constexpr uint8_t ack = 0x1;
+                connection->send(H2::Frame(H2::Frame::Type::Ping, ack, frame.streamID(), frame.payload()));
+            }
+            break;
+        default:
+            // If anything else is sent by the client, preconnect is doing too much.
+            ASSERT_NOT_REACHED();
+            break;
+        }
+        pingPong(WTFMove(connection), headersCount);
+    });
 }
 
+// This should remain disabled until rdar://problem/65055930 is integrated and bots are updated
+TEST(Preconnect, DISABLED_H2Ping)
+{
+    size_t headersCount = 0;
+    HTTPServer server([headersCount = &headersCount] (Connection tlsConnection) {
+        pingPong(H2::Connection::create(tlsConnection), headersCount);
+    }, HTTPServer::Protocol::Http2);
+    
+    auto delegate = adoptNS([SessionDelegate new]);
+    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:delegate.get() delegateQueue:[NSOperationQueue mainQueue]];
+    NSURLSessionDataTask *task = [session dataTaskWithRequest:server.request()];
+    task._preconnect = YES;
+    __block bool done = false;
+
+    [task getUnderlyingHTTPConnectionInfoWithCompletionHandler:^(_NSHTTPConnectionInfo *connectionInfo) {
+        EXPECT_TRUE(connectionInfo.isValid);
+        [connectionInfo sendPingWithReceiveHandler:^(NSError *error, NSTimeInterval interval) {
+            EXPECT_FALSE(error);
+            EXPECT_GT(interval, 0.0);
+            done = true;
+        }];
+    }];
+    [task resume];
+    Util::run(&done);
+    
+    // Make sure the client doesn't send anything except Settings, WindowUpdate, and Ping.
+    // If Headers or Data were sent, then the preconnect wouldn't be preconnect.
+    usleep(100000);
+    Util::spinRunLoop(100);
+    EXPECT_EQ(headersCount, 0u);
+
+    NSURLSessionDataTask *task2 = [session dataTaskWithRequest:server.request()];
+    [task2 resume];
+    while (!headersCount)
+        Util::spinRunLoop();
+    EXPECT_EQ(headersCount, 1u);
+    usleep(100000);
+    Util::spinRunLoop(100);
+    EXPECT_EQ(headersCount, 1u);
+}
+#endif // HAVE(PRECONNECT_PING)
+
+}
+
 #endif

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h (263878 => 263879)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h	2020-07-03 02:01:21 UTC (rev 263879)
@@ -43,7 +43,7 @@
 public:
     struct HTTPResponse;
     struct RequestData;
-    enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS };
+    enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS, Http2 };
     using CertificateVerifier = Function<void(sec_protocol_metadata_t, sec_trust_t, sec_protocol_verify_complete_t)>;
 
     HTTPServer(std::initializer_list<std::pair<String, HTTPResponse>>, Protocol = Protocol::Http, CertificateVerifier&& = nullptr);
@@ -67,6 +67,9 @@
 class Connection {
 public:
     void send(String&&, CompletionHandler<void()>&& = nullptr) const;
+    void send(Vector<uint8_t>&&, CompletionHandler<void()>&& = nullptr) const;
+    void send(RetainPtr<dispatch_data_t>&&, CompletionHandler<void()>&& = nullptr) const;
+    void receiveBytes(CompletionHandler<void(Vector<uint8_t>&&)>&&) const;
     void receiveHTTPRequest(CompletionHandler<void(Vector<char>&&)>&&, Vector<char>&& buffer = { }) const;
     void terminate() const;
 
@@ -105,6 +108,61 @@
     TerminateConnection terminateConnection { TerminateConnection::No };
 };
 
+namespace H2 {
+
+// https://http2.github.io/http2-spec/#rfc.section.4.1
+class Frame {
+public:
+
+    // https://http2.github.io/http2-spec/#rfc.section.6
+    enum class Type : uint8_t {
+        Data = ""
+        Headers = 0x1,
+        Priority = 0x2,
+        RSTStream = 0x3,
+        Settings = 0x4,
+        PushPromise = 0x5,
+        Ping = 0x6,
+        GoAway = 0x7,
+        WindowUpdate = 0x8,
+        Continuation = 0x9,
+    };
+
+    Frame(Type type, uint8_t flags, uint32_t streamID, Vector<uint8_t> payload)
+        : m_type(type)
+        , m_flags(flags)
+        , m_streamID(streamID)
+        , m_payload(WTFMove(payload)) { }
+
+    Type type() const { return m_type; }
+    uint8_t flags() const { return m_flags; }
+    uint32_t streamID() const { return m_streamID; }
+    const Vector<uint8_t>& payload() const { return m_payload; }
+
+private:
+    Type m_type;
+    uint8_t m_flags;
+    uint32_t m_streamID;
+    Vector<uint8_t> m_payload;
+};
+
+class Connection : public RefCounted<Connection> {
+public:
+    static Ref<Connection> create(TestWebKitAPI::Connection tlsConnection) { return adoptRef(*new Connection(tlsConnection)); }
+    void send(Frame&&, CompletionHandler<void()>&& = nullptr) const;
+    void receive(CompletionHandler<void(Frame&&)>&&) const;
+private:
+    Connection(TestWebKitAPI::Connection tlsConnection)
+        : m_tlsConnection(tlsConnection) { }
+
+    TestWebKitAPI::Connection m_tlsConnection;
+    mutable bool m_expectClientConnectionPreface { true };
+    mutable bool m_sendServerConnectionPreface { true };
+    mutable Vector<uint8_t> m_receiveBuffer;
+};
+
+} // namespace H2
+
 } // namespace TestWebKitAPI
 
 #endif // HAVE(NETWORK_FRAMEWORK)

Modified: trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm (263878 => 263879)


--- trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2020-07-03 01:05:35 UTC (rev 263878)
+++ trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm	2020-07-03 02:01:21 UTC (rev 263879)
@@ -66,6 +66,8 @@
                 verifier(metadata, trust, completion);
             }).get(), dispatch_get_main_queue());
         }
+        if (protocol == Protocol::Http2)
+            sec_protocol_options_add_tls_application_protocol(options.get(), "h2");
 #else
         UNUSED_PARAM(protocolOptions);
         ASSERT_UNUSED(protocol, protocol != Protocol::HttpsWithLegacyTLS);
@@ -165,9 +167,19 @@
     }));
 }
 
-static Vector<char> vectorFromData(dispatch_data_t content)
+static RetainPtr<dispatch_data_t> dataFromVector(Vector<uint8_t>&& v)
 {
-    __block Vector<char> request;
+    auto bufferSize = v.size();
+    auto rawPointer = v.releaseBuffer().leakPtr();
+    return adoptNS(dispatch_data_create(rawPointer, bufferSize, dispatch_get_main_queue(), ^{
+        fastFree(rawPointer);
+    }));
+}
+
+static Vector<uint8_t> vectorFromData(dispatch_data_t content)
+{
+    ASSERT(content);
+    __block Vector<uint8_t> request;
     dispatch_data_apply(content, ^bool(dispatch_data_t, size_t, const void* buffer, size_t size) {
         request.append(static_cast<const char*>(buffer), size);
         return true;
@@ -227,6 +239,7 @@
         break;
     case Protocol::Https:
     case Protocol::HttpsWithLegacyTLS:
+    case Protocol::Http2:
         format = @"https://127.0.0.1:%d%s";
         break;
     }
@@ -233,12 +246,19 @@
     return [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:format, port(), path.utf8().data()]]];
 }
 
-void Connection::receiveHTTPRequest(CompletionHandler<void(Vector<char>&&)>&& completionHandler, Vector<char>&& buffer) const
+void Connection::receiveBytes(CompletionHandler<void(Vector<uint8_t>&&)>&& completionHandler) const
 {
-    nw_connection_receive(m_connection.get(), 1, std::numeric_limits<uint32_t>::max(), makeBlockPtr([connection = *this, completionHandler = WTFMove(completionHandler), buffer = WTFMove(buffer)](dispatch_data_t content, nw_content_context_t, bool, nw_error_t error) mutable {
+    nw_connection_receive(m_connection.get(), 1, std::numeric_limits<uint32_t>::max(), makeBlockPtr([connection = *this, completionHandler = WTFMove(completionHandler)](dispatch_data_t content, nw_content_context_t, bool, nw_error_t error) mutable {
         if (error || !content)
             return completionHandler({ });
-        buffer.appendVector(vectorFromData(content));
+        completionHandler(vectorFromData(content));
+    }).get());
+}
+
+void Connection::receiveHTTPRequest(CompletionHandler<void(Vector<char>&&)>&& completionHandler, Vector<char>&& buffer) const
+{
+    receiveBytes([connection = *this, completionHandler = WTFMove(completionHandler), buffer = WTFMove(buffer)](Vector<uint8_t>&& bytes) mutable {
+        buffer.appendVector(WTFMove(bytes));
         if (auto* doubleNewline = strnstr(buffer.data(), "\r\n\r\n", buffer.size())) {
             if (auto* contentLengthBegin = strnstr(buffer.data(), "Content-Length", buffer.size())) {
                 size_t contentLength = atoi(contentLengthBegin + strlen("Content-Length: "));
@@ -249,12 +269,22 @@
             completionHandler(WTFMove(buffer));
         } else
             connection.receiveHTTPRequest(WTFMove(completionHandler), WTFMove(buffer));
-    }).get());
+    });
 }
 
 void Connection::send(String&& message, CompletionHandler<void()>&& completionHandler) const
 {
-    nw_connection_send(m_connection.get(), dataFromString(WTFMove(message)).get(), NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, makeBlockPtr([completionHandler = WTFMove(completionHandler)](nw_error_t error) mutable {
+    send(dataFromString(WTFMove(message)), WTFMove(completionHandler));
+}
+
+void Connection::send(Vector<uint8_t>&& message, CompletionHandler<void()>&& completionHandler) const
+{
+    send(dataFromVector(WTFMove(message)), WTFMove(completionHandler));
+}
+
+void Connection::send(RetainPtr<dispatch_data_t>&& message, CompletionHandler<void()>&& completionHandler) const
+{
+    nw_connection_send(m_connection.get(), message.get(), NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, makeBlockPtr([completionHandler = WTFMove(completionHandler)](nw_error_t error) mutable {
         ASSERT(!error);
         if (completionHandler)
             completionHandler();
@@ -266,6 +296,79 @@
     nw_connection_cancel(m_connection.get());
 }
 
+void H2::Connection::send(Frame&& frame, CompletionHandler<void()>&& completionHandler) const
+{
+    auto frameType = frame.type();
+    auto sendFrame = [tlsConnection = m_tlsConnection, frame = WTFMove(frame), completionHandler = WTFMove(completionHandler)] () mutable {
+        // https://http2.github.io/http2-spec/#rfc.section.4.1
+        Vector<uint8_t> bytes;
+        constexpr size_t frameHeaderLength = 9;
+        bytes.reserveInitialCapacity(frameHeaderLength + frame.payload().size());
+        bytes.uncheckedAppend(frame.payload().size() >> 16);
+        bytes.uncheckedAppend(frame.payload().size() >> 8);
+        bytes.uncheckedAppend(frame.payload().size() >> 0);
+        bytes.uncheckedAppend(static_cast<uint8_t>(frame.type()));
+        bytes.uncheckedAppend(frame.flags());
+        bytes.uncheckedAppend(frame.streamID() >> 24);
+        bytes.uncheckedAppend(frame.streamID() >> 16);
+        bytes.uncheckedAppend(frame.streamID() >> 8);
+        bytes.uncheckedAppend(frame.streamID() >> 0);
+        bytes.appendVector(frame.payload());
+        tlsConnection.send(WTFMove(bytes), WTFMove(completionHandler));
+    };
+
+    if (m_sendServerConnectionPreface && frameType != Frame::Type::Settings) {
+        // https://http2.github.io/http2-spec/#rfc.section.3.5
+        m_sendServerConnectionPreface = false;
+        send(Frame(Frame::Type::Settings, 0, 0, { }), WTFMove(sendFrame));
+    } else
+        sendFrame();
+}
+
+void H2::Connection::receive(CompletionHandler<void(Frame&&)>&& completionHandler) const
+{
+    if (m_expectClientConnectionPreface) {
+        // https://http2.github.io/http2-spec/#rfc.section.3.5
+        constexpr size_t clientConnectionPrefaceLength = 24;
+        if (m_receiveBuffer.size() < clientConnectionPrefaceLength) {
+            m_tlsConnection.receiveBytes([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (Vector<uint8_t>&& bytes) mutable {
+                m_receiveBuffer.appendVector(bytes);
+                receive(WTFMove(completionHandler));
+            });
+            return;
+        }
+        ASSERT(!memcmp(m_receiveBuffer.data(), "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", clientConnectionPrefaceLength));
+        m_receiveBuffer.remove(0, clientConnectionPrefaceLength);
+        m_expectClientConnectionPreface = false;
+        return receive(WTFMove(completionHandler));
+    }
+
+    // https://http2.github.io/http2-spec/#rfc.section.4.1
+    constexpr size_t frameHeaderLength = 9;
+    if (m_receiveBuffer.size() >= frameHeaderLength) {
+        uint32_t payloadLength = (static_cast<uint32_t>(m_receiveBuffer[0]) << 16)
+            + (static_cast<uint32_t>(m_receiveBuffer[1]) << 8)
+            + (static_cast<uint32_t>(m_receiveBuffer[2]) << 0);
+        if (m_receiveBuffer.size() >= frameHeaderLength + payloadLength) {
+            auto type = static_cast<Frame::Type>(m_receiveBuffer[3]);
+            auto flags = m_receiveBuffer[4];
+            auto streamID = (static_cast<uint32_t>(m_receiveBuffer[5]) << 24)
+                + (static_cast<uint32_t>(m_receiveBuffer[6]) << 16)
+                + (static_cast<uint32_t>(m_receiveBuffer[7]) << 8)
+                + (static_cast<uint32_t>(m_receiveBuffer[8]) << 0);
+            Vector<uint8_t> payload;
+            payload.append(m_receiveBuffer.data() + frameHeaderLength, payloadLength);
+            m_receiveBuffer.remove(0, frameHeaderLength + payloadLength);
+            return completionHandler(Frame(type, flags, streamID, WTFMove(payload)));
+        }
+    }
+    
+    m_tlsConnection.receiveBytes([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (Vector<uint8_t>&& bytes) mutable {
+        m_receiveBuffer.appendVector(bytes);
+        receive(WTFMove(completionHandler));
+    });
+}
+
 } // namespace TestWebKitAPI
 
 #endif // HAVE(NETWORK_FRAMEWORK)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to