Changeset 263879 in webkit
- Timestamp:
- Jul 2, 2020, 7:01:21 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/wtf/PlatformHave.h (modified) (1 diff)
-
Source/WebCore/PAL/ChangeLog (modified) (1 diff)
-
Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm (modified) (2 diffs)
-
Tools/TestWebKitAPI/cocoa/HTTPServer.h (modified) (3 diffs)
-
Tools/TestWebKitAPI/cocoa/HTTPServer.mm (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r263819 r263879 1 2020-07-02 Alex Christensen <achristensen@webkit.org> 2 3 Add testing infrastructure and SPI declaration for HTTP/2 ping 4 https://bugs.webkit.org/show_bug.cgi?id=213913 5 6 Reviewed by Jer Noble. 7 8 This is work towards rdar://problem/64495827 9 10 * wtf/PlatformHave.h: 11 1 12 2020-07-01 Tim Horton <timothy_horton@apple.com> 2 13 -
trunk/Source/WTF/wtf/PlatformHave.h
r263819 r263879 381 381 #endif 382 382 383 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101600) \ 384 || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 140000) \ 385 || (PLATFORM(WATCHOS) && __WATCH_OS_VERSION_MIN_REQUIRED >= 70000) \ 386 || (PLATFORM(APPLETV) && __TV_OS_VERSION_MIN_REQUIRED >= 140000) \ 387 || (PLATFORM(MACCATALYST) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 140000) 388 #define HAVE_PRECONNECT_PING 1 389 #endif 390 383 391 #if PLATFORM(COCOA) && !(PLATFORM(MAC) && !(__MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101404)) 384 392 #define HAVE_CFNETWORK_OVERRIDE_SESSION_COOKIE_ACCEPT_POLICY 1 -
trunk/Source/WebCore/PAL/ChangeLog
r263819 r263879 1 2020-07-02 Alex Christensen <achristensen@webkit.org> 2 3 Add testing infrastructure and SPI declaration for HTTP/2 ping 4 https://bugs.webkit.org/show_bug.cgi?id=213913 5 6 Reviewed by Jer Noble. 7 8 * pal/spi/cf/CFNetworkSPI.h: 9 1 10 2020-07-01 Tim Horton <timothy_horton@apple.com> 2 11 -
trunk/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h
r263736 r263879 67 67 68 68 #else // !PLATFORM(WIN) && !USE(APPLE_INTERNAL_SDK) 69 70 #if HAVE(PRECONNECT_PING) 71 @interface _NSHTTPConnectionInfo : NSObject 72 - (void)sendPingWithReceiveHandler:(void (^)(NSError * _Nullable error, NSTimeInterval interval))pongHandler; 73 @property (readonly) BOOL isValid; 74 @end 75 76 @interface NSURLSessionTask (HTTPConnectionInfo) 77 - (void)getUnderlyingHTTPConnectionInfoWithCompletionHandler:(void (^)(_NSHTTPConnectionInfo *connectionInfo))completionHandler; 78 @end 79 #endif // HAVE(PRECONNECT_PING) 69 80 70 81 #if HAVE(LOGGING_PRIVACY_LEVEL) -
trunk/Tools/ChangeLog
r263874 r263879 1 2020-07-02 Alex Christensen <achristensen@webkit.org> 2 3 Add testing infrastructure and SPI declaration for HTTP/2 ping 4 https://bugs.webkit.org/show_bug.cgi?id=213913 5 6 Reviewed by Jer Noble. 7 8 * TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm: 9 (-[SessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]): 10 (TestWebKitAPI::pingPong): 11 (TestWebKitAPI::TEST): 12 * TestWebKitAPI/cocoa/HTTPServer.h: 13 (TestWebKitAPI::H2::Frame::Frame): 14 (TestWebKitAPI::H2::Frame::type const): 15 (TestWebKitAPI::H2::Frame::flags const): 16 (TestWebKitAPI::H2::Frame::streamID const): 17 (TestWebKitAPI::H2::Frame::payload const): 18 (TestWebKitAPI::H2::Connection::create): 19 (TestWebKitAPI::H2::Connection::Connection): 20 * TestWebKitAPI/cocoa/HTTPServer.mm: 21 (TestWebKitAPI::HTTPServer::listenerParameters): 22 (TestWebKitAPI::dataFromVector): 23 (TestWebKitAPI::vectorFromData): 24 (TestWebKitAPI::HTTPServer::request const): 25 (TestWebKitAPI::Connection::receiveBytes const): 26 (TestWebKitAPI::Connection::receiveHTTPRequest const): 27 (TestWebKitAPI::Connection::send const): 28 (TestWebKitAPI::H2::Connection::send const): 29 (TestWebKitAPI::H2::Connection::receive const): 30 1 31 2020-07-02 Kate Cheney <katherine_cheney@apple.com> 2 32 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Preconnect.mm
r263242 r263879 33 33 #import "Utilities.h" 34 34 #import <WebKit/WKWebViewPrivate.h> 35 #import <pal/spi/cf/CFNetworkSPI.h> 35 36 #import <wtf/RetainPtr.h> 37 38 #if HAVE(PRECONNECT_PING) 39 @interface SessionDelegate : NSObject <NSURLSessionDataDelegate> 40 @end 41 42 @implementation SessionDelegate 43 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler 44 { 45 completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); 46 } 47 @end 48 #endif 36 49 37 50 namespace TestWebKitAPI { … … 91 104 #endif 92 105 106 #if HAVE(PRECONNECT_PING) 107 static void pingPong(Ref<H2::Connection>&& connection, size_t* headersCount) 108 { 109 connection->receive([connection, headersCount] (H2::Frame&& frame) mutable { 110 switch (frame.type()) { 111 case H2::Frame::Type::Headers: 112 ++*headersCount; 113 break; 114 case H2::Frame::Type::Settings: 115 case H2::Frame::Type::WindowUpdate: 116 // These frame types are ok for a preconnect task. 117 break; 118 case H2::Frame::Type::Ping: 119 { 120 // https://http2.github.io/http2-spec/#rfc.section.6.7 121 constexpr uint8_t ack = 0x1; 122 connection->send(H2::Frame(H2::Frame::Type::Ping, ack, frame.streamID(), frame.payload())); 123 } 124 break; 125 default: 126 // If anything else is sent by the client, preconnect is doing too much. 127 ASSERT_NOT_REACHED(); 128 break; 129 } 130 pingPong(WTFMove(connection), headersCount); 131 }); 132 } 133 134 // This should remain disabled until rdar://problem/65055930 is integrated and bots are updated 135 TEST(Preconnect, DISABLED_H2Ping) 136 { 137 size_t headersCount = 0; 138 HTTPServer server([headersCount = &headersCount] (Connection tlsConnection) { 139 pingPong(H2::Connection::create(tlsConnection), headersCount); 140 }, HTTPServer::Protocol::Http2); 141 142 auto delegate = adoptNS([SessionDelegate new]); 143 NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:delegate.get() delegateQueue:[NSOperationQueue mainQueue]]; 144 NSURLSessionDataTask *task = [session dataTaskWithRequest:server.request()]; 145 task._preconnect = YES; 146 __block bool done = false; 147 148 [task getUnderlyingHTTPConnectionInfoWithCompletionHandler:^(_NSHTTPConnectionInfo *connectionInfo) { 149 EXPECT_TRUE(connectionInfo.isValid); 150 [connectionInfo sendPingWithReceiveHandler:^(NSError *error, NSTimeInterval interval) { 151 EXPECT_FALSE(error); 152 EXPECT_GT(interval, 0.0); 153 done = true; 154 }]; 155 }]; 156 [task resume]; 157 Util::run(&done); 158 159 // Make sure the client doesn't send anything except Settings, WindowUpdate, and Ping. 160 // If Headers or Data were sent, then the preconnect wouldn't be preconnect. 161 usleep(100000); 162 Util::spinRunLoop(100); 163 EXPECT_EQ(headersCount, 0u); 164 165 NSURLSessionDataTask *task2 = [session dataTaskWithRequest:server.request()]; 166 [task2 resume]; 167 while (!headersCount) 168 Util::spinRunLoop(); 169 EXPECT_EQ(headersCount, 1u); 170 usleep(100000); 171 Util::spinRunLoop(100); 172 EXPECT_EQ(headersCount, 1u); 173 } 174 #endif // HAVE(PRECONNECT_PING) 175 93 176 } 94 177 -
trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h
r262985 r263879 44 44 struct HTTPResponse; 45 45 struct RequestData; 46 enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS };46 enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS, Http2 }; 47 47 using CertificateVerifier = Function<void(sec_protocol_metadata_t, sec_trust_t, sec_protocol_verify_complete_t)>; 48 48 … … 68 68 public: 69 69 void send(String&&, CompletionHandler<void()>&& = nullptr) const; 70 void send(Vector<uint8_t>&&, CompletionHandler<void()>&& = nullptr) const; 71 void send(RetainPtr<dispatch_data_t>&&, CompletionHandler<void()>&& = nullptr) const; 72 void receiveBytes(CompletionHandler<void(Vector<uint8_t>&&)>&&) const; 70 73 void receiveHTTPRequest(CompletionHandler<void(Vector<char>&&)>&&, Vector<char>&& buffer = { }) const; 71 74 void terminate() const; … … 106 109 }; 107 110 111 namespace H2 { 112 113 // https://http2.github.io/http2-spec/#rfc.section.4.1 114 class Frame { 115 public: 116 117 // https://http2.github.io/http2-spec/#rfc.section.6 118 enum class Type : uint8_t { 119 Data = 0x0, 120 Headers = 0x1, 121 Priority = 0x2, 122 RSTStream = 0x3, 123 Settings = 0x4, 124 PushPromise = 0x5, 125 Ping = 0x6, 126 GoAway = 0x7, 127 WindowUpdate = 0x8, 128 Continuation = 0x9, 129 }; 130 131 Frame(Type type, uint8_t flags, uint32_t streamID, Vector<uint8_t> payload) 132 : m_type(type) 133 , m_flags(flags) 134 , m_streamID(streamID) 135 , m_payload(WTFMove(payload)) { } 136 137 Type type() const { return m_type; } 138 uint8_t flags() const { return m_flags; } 139 uint32_t streamID() const { return m_streamID; } 140 const Vector<uint8_t>& payload() const { return m_payload; } 141 142 private: 143 Type m_type; 144 uint8_t m_flags; 145 uint32_t m_streamID; 146 Vector<uint8_t> m_payload; 147 }; 148 149 class Connection : public RefCounted<Connection> { 150 public: 151 static Ref<Connection> create(TestWebKitAPI::Connection tlsConnection) { return adoptRef(*new Connection(tlsConnection)); } 152 void send(Frame&&, CompletionHandler<void()>&& = nullptr) const; 153 void receive(CompletionHandler<void(Frame&&)>&&) const; 154 private: 155 Connection(TestWebKitAPI::Connection tlsConnection) 156 : m_tlsConnection(tlsConnection) { } 157 158 TestWebKitAPI::Connection m_tlsConnection; 159 mutable bool m_expectClientConnectionPreface { true }; 160 mutable bool m_sendServerConnectionPreface { true }; 161 mutable Vector<uint8_t> m_receiveBuffer; 162 }; 163 164 } // namespace H2 165 108 166 } // namespace TestWebKitAPI 109 167 -
trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm
r262985 r263879 67 67 }).get(), dispatch_get_main_queue()); 68 68 } 69 if (protocol == Protocol::Http2) 70 sec_protocol_options_add_tls_application_protocol(options.get(), "h2"); 69 71 #else 70 72 UNUSED_PARAM(protocolOptions); … … 166 168 } 167 169 168 static Vector<char> vectorFromData(dispatch_data_t content) 169 { 170 __block Vector<char> request; 170 static RetainPtr<dispatch_data_t> dataFromVector(Vector<uint8_t>&& v) 171 { 172 auto bufferSize = v.size(); 173 auto rawPointer = v.releaseBuffer().leakPtr(); 174 return adoptNS(dispatch_data_create(rawPointer, bufferSize, dispatch_get_main_queue(), ^{ 175 fastFree(rawPointer); 176 })); 177 } 178 179 static Vector<uint8_t> vectorFromData(dispatch_data_t content) 180 { 181 ASSERT(content); 182 __block Vector<uint8_t> request; 171 183 dispatch_data_apply(content, ^bool(dispatch_data_t, size_t, const void* buffer, size_t size) { 172 184 request.append(static_cast<const char*>(buffer), size); … … 228 240 case Protocol::Https: 229 241 case Protocol::HttpsWithLegacyTLS: 242 case Protocol::Http2: 230 243 format = @"https://127.0.0.1:%d%s"; 231 244 break; … … 234 247 } 235 248 236 void Connection::receive HTTPRequest(CompletionHandler<void(Vector<char>&&)>&& completionHandler, Vector<char>&& buffer) const237 { 238 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 {249 void Connection::receiveBytes(CompletionHandler<void(Vector<uint8_t>&&)>&& completionHandler) const 250 { 251 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 { 239 252 if (error || !content) 240 253 return completionHandler({ }); 241 buffer.appendVector(vectorFromData(content)); 254 completionHandler(vectorFromData(content)); 255 }).get()); 256 } 257 258 void Connection::receiveHTTPRequest(CompletionHandler<void(Vector<char>&&)>&& completionHandler, Vector<char>&& buffer) const 259 { 260 receiveBytes([connection = *this, completionHandler = WTFMove(completionHandler), buffer = WTFMove(buffer)](Vector<uint8_t>&& bytes) mutable { 261 buffer.appendVector(WTFMove(bytes)); 242 262 if (auto* doubleNewline = strnstr(buffer.data(), "\r\n\r\n", buffer.size())) { 243 263 if (auto* contentLengthBegin = strnstr(buffer.data(), "Content-Length", buffer.size())) { … … 250 270 } else 251 271 connection.receiveHTTPRequest(WTFMove(completionHandler), WTFMove(buffer)); 252 }) .get());272 }); 253 273 } 254 274 255 275 void Connection::send(String&& message, CompletionHandler<void()>&& completionHandler) const 256 276 { 257 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 { 277 send(dataFromString(WTFMove(message)), WTFMove(completionHandler)); 278 } 279 280 void Connection::send(Vector<uint8_t>&& message, CompletionHandler<void()>&& completionHandler) const 281 { 282 send(dataFromVector(WTFMove(message)), WTFMove(completionHandler)); 283 } 284 285 void Connection::send(RetainPtr<dispatch_data_t>&& message, CompletionHandler<void()>&& completionHandler) const 286 { 287 nw_connection_send(m_connection.get(), message.get(), NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, makeBlockPtr([completionHandler = WTFMove(completionHandler)](nw_error_t error) mutable { 258 288 ASSERT(!error); 259 289 if (completionHandler) … … 267 297 } 268 298 299 void H2::Connection::send(Frame&& frame, CompletionHandler<void()>&& completionHandler) const 300 { 301 auto frameType = frame.type(); 302 auto sendFrame = [tlsConnection = m_tlsConnection, frame = WTFMove(frame), completionHandler = WTFMove(completionHandler)] () mutable { 303 // https://http2.github.io/http2-spec/#rfc.section.4.1 304 Vector<uint8_t> bytes; 305 constexpr size_t frameHeaderLength = 9; 306 bytes.reserveInitialCapacity(frameHeaderLength + frame.payload().size()); 307 bytes.uncheckedAppend(frame.payload().size() >> 16); 308 bytes.uncheckedAppend(frame.payload().size() >> 8); 309 bytes.uncheckedAppend(frame.payload().size() >> 0); 310 bytes.uncheckedAppend(static_cast<uint8_t>(frame.type())); 311 bytes.uncheckedAppend(frame.flags()); 312 bytes.uncheckedAppend(frame.streamID() >> 24); 313 bytes.uncheckedAppend(frame.streamID() >> 16); 314 bytes.uncheckedAppend(frame.streamID() >> 8); 315 bytes.uncheckedAppend(frame.streamID() >> 0); 316 bytes.appendVector(frame.payload()); 317 tlsConnection.send(WTFMove(bytes), WTFMove(completionHandler)); 318 }; 319 320 if (m_sendServerConnectionPreface && frameType != Frame::Type::Settings) { 321 // https://http2.github.io/http2-spec/#rfc.section.3.5 322 m_sendServerConnectionPreface = false; 323 send(Frame(Frame::Type::Settings, 0, 0, { }), WTFMove(sendFrame)); 324 } else 325 sendFrame(); 326 } 327 328 void H2::Connection::receive(CompletionHandler<void(Frame&&)>&& completionHandler) const 329 { 330 if (m_expectClientConnectionPreface) { 331 // https://http2.github.io/http2-spec/#rfc.section.3.5 332 constexpr size_t clientConnectionPrefaceLength = 24; 333 if (m_receiveBuffer.size() < clientConnectionPrefaceLength) { 334 m_tlsConnection.receiveBytes([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (Vector<uint8_t>&& bytes) mutable { 335 m_receiveBuffer.appendVector(bytes); 336 receive(WTFMove(completionHandler)); 337 }); 338 return; 339 } 340 ASSERT(!memcmp(m_receiveBuffer.data(), "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", clientConnectionPrefaceLength)); 341 m_receiveBuffer.remove(0, clientConnectionPrefaceLength); 342 m_expectClientConnectionPreface = false; 343 return receive(WTFMove(completionHandler)); 344 } 345 346 // https://http2.github.io/http2-spec/#rfc.section.4.1 347 constexpr size_t frameHeaderLength = 9; 348 if (m_receiveBuffer.size() >= frameHeaderLength) { 349 uint32_t payloadLength = (static_cast<uint32_t>(m_receiveBuffer[0]) << 16) 350 + (static_cast<uint32_t>(m_receiveBuffer[1]) << 8) 351 + (static_cast<uint32_t>(m_receiveBuffer[2]) << 0); 352 if (m_receiveBuffer.size() >= frameHeaderLength + payloadLength) { 353 auto type = static_cast<Frame::Type>(m_receiveBuffer[3]); 354 auto flags = m_receiveBuffer[4]; 355 auto streamID = (static_cast<uint32_t>(m_receiveBuffer[5]) << 24) 356 + (static_cast<uint32_t>(m_receiveBuffer[6]) << 16) 357 + (static_cast<uint32_t>(m_receiveBuffer[7]) << 8) 358 + (static_cast<uint32_t>(m_receiveBuffer[8]) << 0); 359 Vector<uint8_t> payload; 360 payload.append(m_receiveBuffer.data() + frameHeaderLength, payloadLength); 361 m_receiveBuffer.remove(0, frameHeaderLength + payloadLength); 362 return completionHandler(Frame(type, flags, streamID, WTFMove(payload))); 363 } 364 } 365 366 m_tlsConnection.receiveBytes([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (Vector<uint8_t>&& bytes) mutable { 367 m_receiveBuffer.appendVector(bytes); 368 receive(WTFMove(completionHandler)); 369 }); 370 } 371 269 372 } // namespace TestWebKitAPI 270 373
Note:
See TracChangeset
for help on using the changeset viewer.