1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 * 7 */ 8 9 #pragma once 10 11 #include <folly/Expected.h> 12 #include <folly/Optional.h> 13 #include <folly/io/IOBuf.h> 14 #include <folly/io/async/AsyncTransportCertificate.h> 15 #include <quic/QuicConstants.h> 16 #include <quic/api/Observer.h> 17 #include <quic/codec/Types.h> 18 #include <quic/common/SmallVec.h> 19 #include <quic/state/QuicConnectionStats.h> 20 #include <quic/state/QuicPriorityQueue.h> 21 #include <quic/state/StateData.h> 22 23 #include <chrono> 24 #include "folly/Portability.h" 25 26 namespace folly { 27 class EventBase; 28 } 29 30 namespace quic { 31 32 class DSRPacketizationRequestSender; 33 34 class QuicSocket { 35 public: 36 /** 37 * Callback for connection set up events. 38 */ 39 class ConnectionSetupCallback { 40 public: 41 virtual ~ConnectionSetupCallback() = default; 42 43 /** 44 * Called after the transport successfully processes the received packet. 45 */ onFirstPeerPacketProcessed()46 virtual void onFirstPeerPacketProcessed() noexcept {} 47 48 /** 49 * Invoked when the connection setup fails. 50 */ 51 virtual void onConnectionSetupError( 52 std::pair<QuicErrorCode, std::string> code) noexcept = 0; 53 54 /** 55 * Called when the transport is ready to send/receive data. 56 * This can be potentially triggerred immidiately when using 0-RTT. 57 */ onTransportReady()58 virtual void onTransportReady() noexcept {} 59 60 /** 61 * Client only. 62 * Called when the transport becomes replay safe - both crypto keys derived. 63 * Called after onTransportReady() and in case of 0-RTT, unlike 64 * onTransportReady(), signifies full crypto handshake finished. 65 */ onReplaySafe()66 virtual void onReplaySafe() noexcept {} 67 }; 68 69 /** 70 * Callback for connection level events once connection is set up. 71 * The name is temporary until we phase out the old monolithic callback. 72 */ 73 class ConnectionCallbackNew { 74 public: 75 virtual ~ConnectionCallbackNew() = default; 76 77 /** 78 * Invoked when stream id's flow control state changes. This is an edge 79 * triggred API and will be only invoked at the point that the flow control 80 * changes. 81 */ onFlowControlUpdate(StreamId)82 virtual void onFlowControlUpdate(StreamId /*id*/) noexcept {} 83 84 /** 85 * Invoked when the peer creates a new bidirectional stream. The most 86 * common flow would be to set the ReadCallback from here 87 */ 88 virtual void onNewBidirectionalStream(StreamId id) noexcept = 0; 89 90 /** 91 * Invoked when the peer creates a new unidirectional stream. The most 92 * common flow would be to set the ReadCallback from here 93 */ 94 virtual void onNewUnidirectionalStream(StreamId id) noexcept = 0; 95 96 /** 97 * Invoked when a stream receives a StopSending frame from a peer. 98 * The application should reset the stream as part of this callback. 99 */ 100 virtual void onStopSending( 101 StreamId id, 102 ApplicationErrorCode error) noexcept = 0; 103 104 /** 105 * Invoked when the transport initiates close. No callbacks will 106 * be delivered after this 107 */ 108 virtual void onConnectionEnd() noexcept = 0; 109 110 /** 111 * Invoked when the connection closed in error 112 */ 113 virtual void onConnectionError( 114 std::pair<QuicErrorCode, std::string> code) noexcept = 0; 115 116 /** 117 * Called when more bidirectional streams become available for creation 118 * (max local bidirectional stream ID was increased). 119 */ onBidirectionalStreamsAvailable(uint64_t)120 virtual void onBidirectionalStreamsAvailable( 121 uint64_t /*numStreamsAvailable*/) noexcept {} 122 123 /** 124 * Called when more unidirectional streams become available for creation 125 * (max local unidirectional stream ID was increased). 126 */ onUnidirectionalStreamsAvailable(uint64_t)127 virtual void onUnidirectionalStreamsAvailable( 128 uint64_t /*numStreamsAvailable*/) noexcept {} 129 130 /** 131 * Invoked when transport is detected to be app rate limited. 132 */ onAppRateLimited()133 virtual void onAppRateLimited() noexcept {} 134 135 /** 136 * Invoked when we receive a KnobFrame from the peer 137 */ 138 virtual void onKnob(uint64_t,uint64_t,Buf)139 onKnob(uint64_t /*knobSpace*/, uint64_t /*knobId*/, Buf /*knobBlob*/) {} 140 }; 141 142 /** 143 * Callback for connection level events. This callback must be set at all 144 * times. 145 * This callback will be phased out with the two separate callbacks above to 146 * replace it. 147 */ 148 class ConnectionCallback : public ConnectionSetupCallback, 149 public ConnectionCallbackNew {}; 150 151 /** 152 * Information about the transport, similar to what TCP has. 153 */ 154 struct TransportInfo { 155 std::chrono::microseconds srtt{0us}; 156 std::chrono::microseconds rttvar{0us}; 157 std::chrono::microseconds lrtt{0us}; 158 std::chrono::microseconds mrtt{0us}; 159 uint64_t mss{kDefaultUDPSendPacketLen}; 160 CongestionControlType congestionControlType{CongestionControlType::None}; 161 uint64_t writableBytes{0}; 162 uint64_t congestionWindow{0}; 163 uint64_t pacingBurstSize{0}; 164 std::chrono::microseconds pacingInterval{0us}; 165 uint32_t packetsRetransmitted{0}; 166 uint32_t totalPacketsSent{0}; 167 uint32_t totalAckElicitingPacketsSent{0}; 168 uint32_t totalPacketsMarkedLost{0}; 169 uint32_t totalPacketsMarkedLostByPto{0}; 170 uint32_t totalPacketsMarkedLostByReorderingThreshold{0}; 171 uint32_t totalPacketsSpuriouslyMarkedLost{0}; 172 uint32_t timeoutBasedLoss{0}; 173 std::chrono::microseconds pto{0us}; 174 // Number of Bytes (packet header + body) that were sent 175 uint64_t bytesSent{0}; 176 // Number of Bytes (packet header + body) that were acked 177 uint64_t bytesAcked{0}; 178 // Number of Bytes (packet header + body) that were received 179 uint64_t bytesRecvd{0}; 180 // Number of Bytes (packet header + body) that are in-flight 181 uint64_t bytesInFlight{0}; 182 // Number of Bytes (packet header + body) that were retxed 183 uint64_t totalBytesRetransmitted{0}; 184 // Number of Bytes (only the encoded packet's body) that were sent 185 uint64_t bodyBytesSent{0}; 186 // Number of Bytes (only the encoded packet's body) that were acked 187 uint64_t bodyBytesAcked{0}; 188 // Total number of stream bytes sent on this connection. 189 // Includes retransmissions of stream bytes. 190 uint64_t totalStreamBytesSent{0}; 191 // Total number of 'new' stream bytes sent on this connection. 192 // Does not include retransmissions of stream bytes. 193 uint64_t totalNewStreamBytesSent{0}; 194 uint32_t ptoCount{0}; 195 uint32_t totalPTOCount{0}; 196 folly::Optional<PacketNum> largestPacketAckedByPeer; 197 folly::Optional<PacketNum> largestPacketSent; 198 bool usedZeroRtt; 199 }; 200 201 /** 202 * Information about the stream level transport info. Specific to QUIC. 203 */ 204 struct StreamTransportInfo { 205 // Total time the stream has spent in head-of-line blocked state, 206 // in microseconds 207 std::chrono::microseconds totalHeadOfLineBlockedTime{0us}; 208 209 // How many times the stream has entered the "head-of-line blocked" state 210 uint32_t holbCount{0}; 211 212 // Is the stream head-of-line blocked? 213 bool isHolb{false}; 214 215 // Number of packets transmitted that carry new STREAM frame for this stream 216 uint64_t numPacketsTxWithNewData{0}; 217 }; 218 219 /** 220 * Sets connection callback, must be set BEFORE using the socket. 221 */ 222 virtual void setConnectionCallback(ConnectionCallback* callback) = 0; 223 224 /** 225 * Sets connection setup callback. This callback must be set before using the 226 * socket. 227 */ 228 virtual void setConnectionSetupCallback( 229 ConnectionSetupCallback* callback) = 0; 230 231 /** 232 * Sets connection streams callback. This callback must be set after 233 * connection set up is finished and is ready for streams processing. 234 */ 235 virtual void setConnectionCallbackNew(ConnectionCallbackNew* callback) = 0; 236 237 /** 238 * Sets the functions that mvfst will invoke to validate early data params 239 * and encode early data params to NewSessionTicket. 240 * It's up to the application's responsibility to make sure captured objects 241 * (if any) are alive when the functions are called. 242 * 243 * validator: 244 * On server side: 245 * Called during handshake while negotiating early data. 246 * @param alpn 247 * The negotiated ALPN. Optional because it may be absent from 248 * ClientHello. 249 * @param appParams 250 * The encoded and encrypted application parameters from PSK. 251 * @return 252 * Whether application accepts parameters from resumption state for 253 * 0-RTT. 254 * On client side: 255 * Called when transport is applying psk from cache. 256 * @param alpn 257 * The ALPN client is going to use for this connection. Optional 258 * because client may not set ALPN. 259 * @param appParams 260 * The encoded (not encrypted) application parameter from local cache. 261 * @return 262 * Whether application will attempt early data based on the cached 263 * application parameters. This is useful when client updates to use a 264 * new binary but still reads PSK from an old cache. Client may choose 265 * to not attempt 0-RTT at all given client thinks server will likely 266 * reject it. 267 * 268 * getter: 269 * On server side: 270 * Called when transport is writing NewSessionTicket. 271 * @return 272 * The encoded application parameters that will be included in 273 * NewSessionTicket. 274 * On client side: 275 * Called when client receives NewSessionTicket and is going to write to 276 * cache. 277 * @return 278 * Encoded application parameters that will be written to cache. 279 */ 280 virtual void setEarlyDataAppParamsFunctions( 281 folly::Function< 282 bool(const folly::Optional<std::string>& alpn, const Buf& appParams) 283 const> validator, 284 folly::Function<Buf()> getter) = 0; 285 286 virtual ~QuicSocket() = default; 287 288 /** 289 * ===== Generic Socket Methods ===== 290 */ 291 292 /** 293 * Get the QUIC Client Connection ID 294 */ 295 virtual folly::Optional<ConnectionId> getClientConnectionId() const = 0; 296 297 /** 298 * Get the QUIC Server Connection ID 299 */ 300 virtual folly::Optional<ConnectionId> getServerConnectionId() const = 0; 301 302 /** 303 * Get the original Quic Server Connection ID chosen by client 304 */ 305 FOLLY_NODISCARD virtual folly::Optional<ConnectionId> 306 getClientChosenDestConnectionId() const = 0; 307 308 /** 309 * Get the peer socket address 310 */ 311 virtual const folly::SocketAddress& getPeerAddress() const = 0; 312 313 /** 314 * Get the original peer socket address 315 */ 316 virtual const folly::SocketAddress& getOriginalPeerAddress() const = 0; 317 318 /** 319 * Get the local socket address 320 */ 321 virtual const folly::SocketAddress& getLocalAddress() const = 0; 322 323 /** 324 * Get the cert presented by peer 325 */ 326 FOLLY_NODISCARD virtual const std::shared_ptr< 327 const folly::AsyncTransportCertificate> getPeerCertificate()328 getPeerCertificate() const { 329 return nullptr; 330 } 331 332 /** 333 * Determine if transport is open and ready to read or write. 334 * 335 * return true iff the transport is open and ready, false otherwise. 336 */ 337 virtual bool good() const = 0; 338 339 virtual bool replaySafe() const = 0; 340 341 /** 342 * Determine if an error has occurred with this transport. 343 */ 344 virtual bool error() const = 0; 345 346 /** 347 * Close this socket with a drain period. If closing with an error, it may be 348 * specified. 349 */ 350 virtual void close( 351 folly::Optional<std::pair<QuicErrorCode, std::string>> errorCode) = 0; 352 353 /** 354 * Close this socket gracefully, by waiting for all the streams to be idle 355 * first. 356 */ 357 virtual void closeGracefully() = 0; 358 359 /** 360 * Close this socket without a drain period. If closing with an error, it may 361 * be specified. 362 */ 363 virtual void closeNow( 364 folly::Optional<std::pair<QuicErrorCode, std::string>> errorCode) = 0; 365 366 /** 367 * Returns the event base associated with this socket 368 */ 369 virtual folly::EventBase* getEventBase() const = 0; 370 371 /** 372 * Returns the current offset already read or written by the application on 373 * the given stream. 374 */ 375 virtual folly::Expected<size_t, LocalErrorCode> getStreamReadOffset( 376 StreamId id) const = 0; 377 virtual folly::Expected<size_t, LocalErrorCode> getStreamWriteOffset( 378 StreamId id) const = 0; 379 /** 380 * Returns the amount of data buffered by the transport waiting to be written 381 */ 382 virtual folly::Expected<size_t, LocalErrorCode> getStreamWriteBufferedBytes( 383 StreamId id) const = 0; 384 385 /** 386 * Get internal transport info similar to TCP information. 387 */ 388 virtual TransportInfo getTransportInfo() const = 0; 389 390 /** 391 * Get internal transport info similar to TCP information. 392 * Returns LocalErrorCode::STREAM_NOT_EXISTS if the stream is not found 393 */ 394 virtual folly::Expected<StreamTransportInfo, LocalErrorCode> 395 getStreamTransportInfo(StreamId id) const = 0; 396 397 /** 398 * Get the negotiated ALPN. If called before the transport is ready 399 * returns folly::none 400 */ 401 virtual folly::Optional<std::string> getAppProtocol() const = 0; 402 403 /** 404 * Sets the size of the given stream's receive window, or the connection 405 * receive window if stream id is 0. If the window size increases, a 406 * window update will be sent to the peer. If it decreases, the transport 407 * will delay future window updates until the sender's available window is 408 * <= recvWindowSize. 409 */ 410 virtual void setReceiveWindow(StreamId id, size_t recvWindowSize) = 0; 411 412 /** 413 * Set the size of the transport send buffer for the given stream. 414 * The maximum total amount of buffer space is the sum of maxUnacked and 415 * maxUnsent. Bytes passed to writeChain count against unsent until the 416 * transport flushes them to the wire, after which they count against unacked. 417 */ 418 virtual void 419 setSendBuffer(StreamId id, size_t maxUnacked, size_t maxUnsent) = 0; 420 421 /** 422 * Return the amount of transport buffer space available for writing 423 */ 424 virtual uint64_t getConnectionBufferAvailable() const = 0; 425 426 /** 427 * Application can invoke this function to signal the transport to 428 * initiate migration. 429 * @param socket The new socket that should be used by the transport. 430 * If this is null then do not replace the underlying socket. 431 */ onNetworkSwitch(std::unique_ptr<folly::AsyncUDPSocket>)432 virtual void onNetworkSwitch(std::unique_ptr<folly::AsyncUDPSocket>) {} 433 434 /** 435 * Get the flow control settings for the given stream (or connection flow 436 * control by passing id=0). Settings include send and receive window 437 * capacity and available. 438 */ 439 struct FlowControlState { 440 // Number of bytes the peer has allowed me to send. 441 uint64_t sendWindowAvailable; 442 // The max offset provided by the peer. 443 uint64_t sendWindowMaxOffset; 444 // Number of bytes I have allowed the peer to send. 445 uint64_t receiveWindowAvailable; 446 // The max offset I have provided to the peer. 447 uint64_t receiveWindowMaxOffset; 448 FlowControlStateFlowControlState449 FlowControlState( 450 uint64_t sendWindowAvailableIn, 451 uint64_t sendWindowMaxOffsetIn, 452 uint64_t receiveWindowAvailableIn, 453 uint64_t receiveWindowMaxOffsetIn) 454 : sendWindowAvailable(sendWindowAvailableIn), 455 sendWindowMaxOffset(sendWindowMaxOffsetIn), 456 receiveWindowAvailable(receiveWindowAvailableIn), 457 receiveWindowMaxOffset(receiveWindowMaxOffsetIn) {} 458 }; 459 460 /** 461 * Returns the current flow control windows for the connection. 462 * Use getStreamFlowControl for stream flow control window. 463 */ 464 virtual folly::Expected<FlowControlState, LocalErrorCode> 465 getConnectionFlowControl() const = 0; 466 467 /** 468 * Returns the current flow control windows for the stream, id != 0. 469 * Use getConnectionFlowControl for connection flow control window. 470 */ 471 virtual folly::Expected<FlowControlState, LocalErrorCode> 472 getStreamFlowControl(StreamId id) const = 0; 473 474 /** 475 * Sets the flow control window for the connection. 476 * Use setStreamFlowControlWindow for per Stream flow control. 477 */ 478 virtual folly::Expected<folly::Unit, LocalErrorCode> 479 setConnectionFlowControlWindow(uint64_t windowSize) = 0; 480 481 /** 482 * Sets the flow control window for the stream. 483 * Use setConnectionFlowControlWindow for connection flow control. 484 */ 485 virtual folly::Expected<folly::Unit, LocalErrorCode> 486 setStreamFlowControlWindow(StreamId id, uint64_t windowSize) = 0; 487 488 /** 489 * Settings for the transport. This takes effect only before the transport 490 * is connected. 491 */ 492 virtual void setTransportSettings(TransportSettings transportSettings) = 0; 493 494 virtual const TransportSettings& getTransportSettings() const = 0; 495 496 /** 497 * Sets the maximum pacing rate in Bytes per second to be used 498 * if pacing is enabled 499 */ 500 virtual folly::Expected<folly::Unit, LocalErrorCode> setMaxPacingRate( 501 uint64_t rateBytesPerSec) = 0; 502 503 /** 504 * Set a "knob". This will emit a knob frame to the peer, which the peer 505 * application can act on by e.g. changing transport settings during the 506 * connection. 507 */ 508 virtual folly::Expected<folly::Unit, LocalErrorCode> 509 setKnob(uint64_t knobSpace, uint64_t knobId, Buf knobBlob) = 0; 510 511 /** 512 * Can Knob Frames be exchanged with the peer on this connection? 513 */ 514 FOLLY_NODISCARD virtual bool isKnobSupported() const = 0; 515 516 /** 517 * Set stream priority. 518 * level: can only be in [0, 7]. 519 */ 520 virtual folly::Expected<folly::Unit, LocalErrorCode> 521 setStreamPriority(StreamId id, PriorityLevel level, bool incremental) = 0; 522 523 /** 524 * Get stream priority. 525 */ 526 virtual folly::Expected<Priority, LocalErrorCode> getStreamPriority( 527 StreamId id) = 0; 528 529 /** 530 * ===== Read API ==== 531 */ 532 533 /** 534 * Callback class for receiving data on a stream 535 */ 536 class ReadCallback { 537 public: 538 virtual ~ReadCallback() = default; 539 540 /** 541 * Called from the transport layer when there is data, EOF or an error 542 * available to read on the given stream ID 543 */ 544 virtual void readAvailable(StreamId id) noexcept = 0; 545 546 /** 547 * Called from the transport layer when there is an error on the stream. 548 */ 549 virtual void readError( 550 StreamId id, 551 std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>> 552 error) noexcept = 0; 553 }; 554 555 /** 556 * Set the read callback for the given stream. Note that read callback is 557 * expected to be set all the time. Removing read callback indicates that 558 * stream is no longer intended to be read again. This will issue a 559 * StopSending if cb is being set to nullptr after previously being not 560 * nullptr. The err parameter is used to control the error sent in the 561 * StopSending. By default when cb is nullptr this function will cause the 562 * transport to send a StopSending frame with 563 * GenericApplicationErrorCode::NO_ERROR. If err is specified to be 564 * folly::none, no StopSending will be sent. 565 */ 566 virtual folly::Expected<folly::Unit, LocalErrorCode> setReadCallback( 567 StreamId id, 568 ReadCallback* cb, 569 folly::Optional<ApplicationErrorCode> err = 570 GenericApplicationErrorCode::NO_ERROR) = 0; 571 572 /** 573 * Convenience function that sets the read callbacks of all streams to be 574 * nullptr. 575 */ 576 virtual void unsetAllReadCallbacks() = 0; 577 578 /** 579 * Convenience function that sets the read callbacks of all streams to be 580 * nullptr. 581 */ 582 virtual void unsetAllPeekCallbacks() = 0; 583 584 /** 585 * Convenience function that cancels delivery callbacks of all streams. 586 */ 587 virtual void unsetAllDeliveryCallbacks() = 0; 588 589 /** 590 * Invoke onCanceled on all the delivery callbacks registered for streamId. 591 */ 592 virtual void cancelDeliveryCallbacksForStream(StreamId streamId) = 0; 593 594 /** 595 * Invoke onCanceled on all the delivery callbacks registered for streamId for 596 * offsets lower than the offset provided. 597 */ 598 virtual void cancelDeliveryCallbacksForStream( 599 StreamId streamId, 600 uint64_t offset) = 0; 601 602 /** 603 * Pause/Resume read callback being triggered when data is available. 604 */ 605 virtual folly::Expected<folly::Unit, LocalErrorCode> pauseRead( 606 StreamId id) = 0; 607 virtual folly::Expected<folly::Unit, LocalErrorCode> resumeRead( 608 StreamId id) = 0; 609 610 /** 611 * Initiates sending of a StopSending frame for a given stream to the peer. 612 * This is called a "solicited reset". On receipt of the StopSending frame 613 * the peer should, but may not, send a ResetStream frame for the requested 614 * stream. A caller can use this function when they are no longer processing 615 * received data on the stream. 616 */ 617 virtual folly::Expected<folly::Unit, LocalErrorCode> stopSending( 618 StreamId id, 619 ApplicationErrorCode error) = 0; 620 621 /** 622 * Read from the given stream, up to maxLen bytes. If maxLen is 0, transport 623 * will return all available bytes. 624 * 625 * The return value is Expected. If the value hasError(), then a read error 626 * occured and it can be obtained with error(). If the value hasValue(), then 627 * value() returns a pair of the data (if any) and the EOF marker. 628 * 629 * Calling read() when there is no data/eof to deliver will return an 630 * EAGAIN-like error code. 631 */ 632 virtual folly::Expected<std::pair<Buf, bool>, LocalErrorCode> read( 633 StreamId id, 634 size_t maxLen) = 0; 635 636 /** 637 * ===== Peek/Consume API ===== 638 */ 639 640 /** 641 * Usage: 642 * class Application { 643 * void onNewBidirectionalStream(StreamId id) { 644 * socket_->setPeekCallback(id, this); 645 * } 646 * 647 * virtual void onDataAvailable( 648 * StreamId id, 649 * const folly::Range<PeekIterator>& peekData) noexcept override 650 * { 651 * auto amount = tryInterpret(peekData); 652 * if (amount) { 653 * socket_->consume(id, amount); 654 * } 655 * } 656 * }; 657 */ 658 659 using PeekIterator = std::deque<StreamBuffer>::const_iterator; 660 class PeekCallback { 661 public: 662 virtual ~PeekCallback() = default; 663 664 /** 665 * Called from the transport layer when there is new data available to 666 * peek on a given stream. 667 * Callback can be called multiple times and it is up to application to 668 * de-dupe already peeked ranges. 669 */ 670 virtual void onDataAvailable( 671 StreamId id, 672 const folly::Range<PeekIterator>& peekData) noexcept = 0; 673 674 /** 675 * Called from the transport layer during peek time when there is an error 676 * on the stream. 677 */ 678 virtual void peekError( 679 StreamId id, 680 std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>> 681 error) noexcept = 0; 682 }; 683 684 virtual folly::Expected<folly::Unit, LocalErrorCode> setPeekCallback( 685 StreamId id, 686 PeekCallback* cb) = 0; 687 688 /** 689 * Pause/Resume peek callback being triggered when data is available. 690 */ 691 virtual folly::Expected<folly::Unit, LocalErrorCode> pausePeek( 692 StreamId id) = 0; 693 virtual folly::Expected<folly::Unit, LocalErrorCode> resumePeek( 694 StreamId id) = 0; 695 696 /** 697 * Peek at the given stream. 698 * 699 * The return value is Expected. If the value hasError(), then a read error 700 * occured and it can be obtained with error(). If the value hasValue(), 701 * indicates that peekCallback has been called. 702 * 703 * The range that is passed to callback is only valid until callback returns, 704 * If caller need to preserve data that range points to - that data has to 705 * be copied. 706 * 707 * Calling peek() when there is no data/eof to deliver will return an 708 * EAGAIN-like error code. 709 */ 710 virtual folly::Expected<folly::Unit, LocalErrorCode> peek( 711 StreamId id, 712 const folly::Function<void(StreamId id, const folly::Range<PeekIterator>&) 713 const>& peekCallback) = 0; 714 715 /** 716 * Consumes data on the given stream, starting from currentReadOffset 717 * 718 * The return value is Expected. If the value hasError(), then a read error 719 * occured and it can be obtained with error(). 720 * 721 * @offset - represents start of consumed range. 722 * Current implementation returns error and currentReadOffset if offset != 723 * currentReadOffset 724 * 725 * Calling consume() when there is no data/eof to deliver 726 * will return an EAGAIN-like error code. 727 * 728 */ 729 virtual folly::Expected< 730 folly::Unit, 731 std::pair<LocalErrorCode, folly::Optional<uint64_t>>> 732 consume(StreamId id, uint64_t offset, size_t amount) = 0; 733 734 /** 735 * Equivalent of calling consume(id, stream->currentReadOffset, amount); 736 */ 737 virtual folly::Expected<folly::Unit, LocalErrorCode> consume( 738 StreamId id, 739 size_t amount) = 0; 740 741 /** 742 * ===== Write API ===== 743 */ 744 745 /** 746 * Creates a bidirectional stream. This assigns a stream ID but does not 747 * send anything to the peer. 748 * 749 * If replaySafe is false, the transport will buffer (up to the send buffer 750 * limits) any writes on this stream until the transport is replay safe. 751 */ 752 virtual folly::Expected<StreamId, LocalErrorCode> createBidirectionalStream( 753 bool replaySafe = true) = 0; 754 755 /** 756 * Creates a unidirectional stream. This assigns a stream ID but does not 757 * send anything to the peer. 758 * 759 * If replaySafe is false, the transport will buffer (up to the send buffer 760 * limits) any writes on this stream until the transport is replay safe. 761 */ 762 virtual folly::Expected<StreamId, LocalErrorCode> createUnidirectionalStream( 763 bool replaySafe = true) = 0; 764 765 /** 766 * Returns the number of bidirectional streams that can be opened. 767 */ 768 virtual uint64_t getNumOpenableBidirectionalStreams() const = 0; 769 770 /** 771 * Returns the number of unidirectional streams that can be opened. 772 */ 773 virtual uint64_t getNumOpenableUnidirectionalStreams() const = 0; 774 775 /** 776 * Returns whether a stream ID represents a client-initiated stream. 777 */ 778 virtual bool isClientStream(StreamId stream) noexcept = 0; 779 780 /** 781 * Returns whether a stream ID represents a server-initiated stream. 782 */ 783 virtual bool isServerStream(StreamId stream) noexcept = 0; 784 785 /** 786 * Returns whether a stream ID represents a unidirectional stream. 787 */ 788 virtual bool isUnidirectionalStream(StreamId stream) noexcept = 0; 789 790 /** 791 * Returns whether a stream ID represents a bidirectional stream. 792 */ 793 virtual bool isBidirectionalStream(StreamId stream) noexcept = 0; 794 795 /** 796 * Callback class for receiving write readiness notifications 797 */ 798 class WriteCallback { 799 public: 800 virtual ~WriteCallback() = default; 801 802 /** 803 * Invoked when stream is ready to write after notifyPendingWriteOnStream 804 * has previously been called. 805 * 806 * maxToSend represents the amount of data that the transport layer expects 807 * to write to the network during this event loop, eg: 808 * min(remaining flow control, remaining send buffer space) 809 */ onStreamWriteReady(StreamId,uint64_t)810 virtual void onStreamWriteReady( 811 StreamId /* id */, 812 uint64_t /* maxToSend */) noexcept {} 813 814 /** 815 * Invoked when connection is ready to write after 816 * notifyPendingWriteOnConnection has previously been called. 817 * 818 * maxToSend represents the amount of data that the transport layer expects 819 * to write to the network during this event loop, eg: 820 * min(remaining flow control, remaining send buffer space) 821 */ onConnectionWriteReady(uint64_t)822 virtual void onConnectionWriteReady(uint64_t /* maxToSend */) noexcept {} 823 824 /** 825 * Invoked when a connection is being torn down after 826 * notifyPendingWriteOnStream has been called 827 */ onStreamWriteError(StreamId,std::pair<QuicErrorCode,folly::Optional<folly::StringPiece>>)828 virtual void onStreamWriteError( 829 StreamId /* id */, 830 std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>> 831 /* error */) noexcept {} 832 833 /** 834 * Invoked when a connection is being torn down after 835 * notifyPendingWriteOnConnection has been called 836 */ onConnectionWriteError(std::pair<QuicErrorCode,folly::Optional<folly::StringPiece>>)837 virtual void onConnectionWriteError( 838 std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>> 839 /* error */) noexcept {} 840 }; 841 842 /** 843 * Inform the transport that there is data to write on this connection 844 * An app shouldn't mix connection and stream calls to this API 845 * Use this if the app wants to do prioritization. 846 */ 847 virtual folly::Expected<folly::Unit, LocalErrorCode> 848 notifyPendingWriteOnConnection(WriteCallback* wcb) = 0; 849 850 /** 851 * Inform the transport that there is data to write on a given stream. 852 * An app shouldn't mix connection and stream calls to this API 853 * Use the Connection call if the app wants to do prioritization. 854 */ 855 virtual folly::Expected<folly::Unit, LocalErrorCode> 856 notifyPendingWriteOnStream(StreamId id, WriteCallback* wcb) = 0; 857 858 virtual folly::Expected<folly::Unit, LocalErrorCode> 859 unregisterStreamWriteCallback(StreamId) = 0; 860 861 /** 862 * Structure used to communicate TX and ACK/Delivery notifications. 863 */ 864 struct ByteEvent { 865 enum class Type { ACK = 1, TX = 2 }; 866 static constexpr std::array<Type, 2> kByteEventTypes = { 867 Type::ACK, 868 Type::TX}; 869 870 StreamId id{0}; 871 uint64_t offset{0}; 872 Type type; 873 874 // sRTT at time of event 875 // TODO(bschlinker): Deprecate, caller can fetch transport state if 876 // desired. 877 std::chrono::microseconds srtt{0us}; 878 }; 879 880 /** 881 * Structure used to communicate cancellation of a ByteEvent. 882 * 883 * According to Dictionary.com, cancellation is more frequent in American 884 * English than cancelation. Yet in American English, the preferred style is 885 * typically not to double the final L, so cancel generally becomes canceled. 886 */ 887 using ByteEventCancellation = ByteEvent; 888 889 /** 890 * Callback class for receiving byte event (TX/ACK) notifications. 891 */ 892 class ByteEventCallback { 893 public: 894 virtual ~ByteEventCallback() = default; 895 896 /** 897 * Invoked when a byte event has been successfully registered. 898 * Since this is a convenience notification and not a mandatory callback, 899 * not marking this as pure virtual. 900 */ onByteEventRegistered(ByteEvent)901 virtual void onByteEventRegistered(ByteEvent /* byteEvent */) {} 902 903 /** 904 * Invoked when the byte event has occurred. 905 */ 906 virtual void onByteEvent(ByteEvent byteEvent) = 0; 907 908 /** 909 * Invoked if byte event is canceled due to reset, shutdown, or other error. 910 */ 911 virtual void onByteEventCanceled(ByteEventCancellation cancellation) = 0; 912 }; 913 914 /** 915 * Callback class for receiving ack notifications 916 */ 917 class DeliveryCallback : public ByteEventCallback { 918 public: 919 virtual ~DeliveryCallback() = default; 920 921 /** 922 * Invoked when the peer has acknowledged the receipt of the specified 923 * offset. rtt is the current RTT estimate for the connection. 924 */ 925 virtual void onDeliveryAck( 926 StreamId id, 927 uint64_t offset, 928 std::chrono::microseconds rtt) = 0; 929 930 /** 931 * Invoked on registered delivery callbacks when the bytes will never be 932 * delivered (due to a reset or other error). 933 */ 934 virtual void onCanceled(StreamId id, uint64_t offset) = 0; 935 936 private: 937 // Temporary shim during transition to ByteEvent onByteEventRegistered(ByteEvent)938 void onByteEventRegistered(ByteEvent /* byteEvent */) final { 939 // Not supported 940 } onByteEvent(ByteEvent byteEvent)941 void onByteEvent(ByteEvent byteEvent) final { 942 CHECK_EQ((int)ByteEvent::Type::ACK, (int)byteEvent.type); // sanity 943 onDeliveryAck(byteEvent.id, byteEvent.offset, byteEvent.srtt); 944 } 945 946 // Temporary shim during transition to ByteEvent onByteEventCanceled(ByteEventCancellation cancellation)947 void onByteEventCanceled(ByteEventCancellation cancellation) final { 948 CHECK_EQ((int)ByteEvent::Type::ACK, (int)cancellation.type); // sanity 949 onCanceled(cancellation.id, cancellation.offset); 950 } 951 }; 952 953 /** 954 * Register a callback to be invoked when the stream offset was transmitted. 955 * 956 * Currently, an offset is considered "transmitted" if it has been written to 957 * to the underlying UDP socket, indicating that it has passed through 958 * congestion control and pacing. In the future, this callback may be 959 * triggered by socket/NIC software or hardware timestamps. 960 * 961 * If the registration fails, the callback (ByteEventCallback* cb) will NEVER 962 * be invoked for anything. If the registration succeeds, the callback is 963 * guaranteed to receive an onByteEventRegistered() notification. 964 */ 965 virtual folly::Expected<folly::Unit, LocalErrorCode> registerTxCallback( 966 const StreamId id, 967 const uint64_t offset, 968 ByteEventCallback* cb) = 0; 969 970 /** 971 * Register a byte event to be triggered when specified event type occurs for 972 * the specified stream and offset. 973 * 974 * If the registration fails, the callback (ByteEventCallback* cb) will NEVER 975 * be invoked for anything. If the registration succeeds, the callback is 976 * guaranteed to receive an onByteEventRegistered() notification. 977 */ 978 virtual folly::Expected<folly::Unit, LocalErrorCode> 979 registerByteEventCallback( 980 const ByteEvent::Type type, 981 const StreamId id, 982 const uint64_t offset, 983 ByteEventCallback* cb) = 0; 984 985 /** 986 * Cancel byte event callbacks for given stream. 987 * 988 * If an offset is provided, cancels only callbacks with an offset less than 989 * or equal to the provided offset, otherwise cancels all callbacks. 990 */ 991 virtual void cancelByteEventCallbacksForStream( 992 const StreamId id, 993 const folly::Optional<uint64_t>& offset = folly::none) = 0; 994 995 /** 996 * Cancel byte event callbacks for given type and stream. 997 * 998 * If an offset is provided, cancels only callbacks with an offset less than 999 * or equal to the provided offset, otherwise cancels all callbacks. 1000 */ 1001 virtual void cancelByteEventCallbacksForStream( 1002 const ByteEvent::Type type, 1003 const StreamId id, 1004 const folly::Optional<uint64_t>& offset = folly::none) = 0; 1005 1006 /** 1007 * Cancel all byte event callbacks of all streams. 1008 */ 1009 virtual void cancelAllByteEventCallbacks() = 0; 1010 1011 /** 1012 * Cancel all byte event callbacks of all streams of the given type. 1013 */ 1014 virtual void cancelByteEventCallbacks(const ByteEvent::Type type) = 0; 1015 1016 /** 1017 * Reset or send a stop sending on all non-control streams. Leaves the 1018 * connection otherwise unmodified. Note this will also trigger the 1019 * onStreamWriteError and readError callbacks immediately. 1020 */ 1021 virtual void resetNonControlStreams( 1022 ApplicationErrorCode error, 1023 folly::StringPiece errorMsg) = 0; 1024 1025 /** 1026 * Get the number of pending byte events for the given stream. 1027 */ 1028 FOLLY_NODISCARD virtual size_t getNumByteEventCallbacksForStream( 1029 const StreamId streamId) const = 0; 1030 1031 /** 1032 * Get the number of pending byte events of specified type for given stream. 1033 */ 1034 FOLLY_NODISCARD virtual size_t getNumByteEventCallbacksForStream( 1035 const ByteEvent::Type type, 1036 const StreamId streamId) const = 0; 1037 1038 /** 1039 * Write data/eof to the given stream. 1040 * 1041 * Passing a delivery callback registers a callback from the transport when 1042 * the peer has acknowledged the receipt of all the data/eof passed to write. 1043 * 1044 * An error code is present if there was an error with the write. 1045 */ 1046 using WriteResult = folly::Expected<folly::Unit, LocalErrorCode>; 1047 virtual WriteResult writeChain( 1048 StreamId id, 1049 Buf data, 1050 bool eof, 1051 ByteEventCallback* cb = nullptr) = 0; 1052 1053 /** 1054 * Write a data representation in the form of BufferMeta to the given stream. 1055 */ 1056 virtual WriteResult writeBufMeta( 1057 StreamId id, 1058 const BufferMeta& data, 1059 bool eof, 1060 ByteEventCallback* cb = nullptr) = 0; 1061 1062 /** 1063 * Set the DSRPacketizationRequestSender for a stream. 1064 */ 1065 virtual WriteResult setDSRPacketizationRequestSender( 1066 StreamId id, 1067 std::unique_ptr<DSRPacketizationRequestSender> sender) = 0; 1068 1069 /** 1070 * Register a callback to be invoked when the peer has acknowledged the 1071 * given offset on the given stream. 1072 */ 1073 virtual folly::Expected<folly::Unit, LocalErrorCode> registerDeliveryCallback( 1074 StreamId id, 1075 uint64_t offset, 1076 ByteEventCallback* cb) = 0; 1077 1078 /** 1079 * Close the stream for writing. Equivalent to writeChain(id, nullptr, true). 1080 */ 1081 virtual folly::Optional<LocalErrorCode> shutdownWrite(StreamId id) = 0; 1082 1083 /** 1084 * Cancel the given stream 1085 */ 1086 virtual folly::Expected<folly::Unit, LocalErrorCode> resetStream( 1087 StreamId id, 1088 ApplicationErrorCode error) = 0; 1089 1090 /** 1091 * Helper method to check a generic error for an Application error, and reset 1092 * the stream with the reciprocal error. 1093 * 1094 * Returns true if the error was an ApplicationErrorCode, and the stream was 1095 * reset. 1096 */ 1097 virtual folly::Expected<folly::Unit, LocalErrorCode> 1098 maybeResetStreamFromReadError(StreamId id, QuicErrorCode error) = 0; 1099 1100 /** 1101 * Callback class for pings 1102 */ 1103 class PingCallback { 1104 public: 1105 virtual ~PingCallback() = default; 1106 1107 /** 1108 * Invoked when the ping is acknowledged 1109 */ 1110 virtual void pingAcknowledged() noexcept = 0; 1111 1112 /** 1113 * Invoked if the ping times out 1114 */ 1115 virtual void pingTimeout() noexcept = 0; 1116 }; 1117 1118 /** 1119 * Send a ping to the peer. When the ping is acknowledged by the peer or 1120 * times out, the transport will invoke the callback. 1121 * 1122 * If 'callback' is nullptr, or pingTimeout is 0, no callback is scheduled. 1123 */ 1124 virtual void sendPing( 1125 PingCallback* callback, 1126 std::chrono::milliseconds pingTimeout) = 0; 1127 1128 /** 1129 * Get information on the state of the quic connection. Should only be used 1130 * for logging. 1131 */ 1132 virtual const QuicConnectionStateBase* getState() const = 0; 1133 1134 /** 1135 * Detaches the eventbase from the socket. This must be called from the 1136 * eventbase of socket. 1137 * Normally this is invoked by an app when the connection is idle, i.e. 1138 * there are no "active" streams on the connection, however an app might 1139 * think that all the streams are closed because it wrote the FIN 1140 * to the QuicSocket, however the QuicSocket might not have delivered the FIN 1141 * to the peer yet. Apps SHOULD use the delivery callback to make sure that 1142 * all writes for the closed stream are finished before detaching the 1143 * connection from the eventbase. 1144 */ 1145 virtual void detachEventBase() = 0; 1146 1147 /** 1148 * Attaches an eventbase to the socket. This must be called from the 1149 * eventbase that needs to be attached and the caller must make sure that 1150 * there is no eventbase already attached to the socket. 1151 */ 1152 virtual void attachEventBase(folly::EventBase* evb) = 0; 1153 1154 /** 1155 * Returns whether or not the eventbase can currently be detached from the 1156 * socket. 1157 */ 1158 virtual bool isDetachable() = 0; 1159 1160 /** 1161 * Signal the transport that a certain stream is a control stream. 1162 * A control stream outlives all the other streams in a connection, therefore, 1163 * if the transport knows about it, can enable some optimizations. 1164 * Applications should declare all their control streams after either calling 1165 * createStream() or receiving onNewBidirectionalStream() 1166 */ 1167 virtual folly::Optional<LocalErrorCode> setControlStream(StreamId id) = 0; 1168 1169 /** 1170 * Set congestion control type. 1171 */ 1172 virtual void setCongestionControl(CongestionControlType type) = 0; 1173 1174 /** 1175 * Adds an observer. 1176 * 1177 * Observers can tie their lifetime to aspects of this socket's / 1178 * lifetime and perform inspection at various states. 1179 * 1180 * This enables instrumentation to be added without changing / interfering 1181 * with how the application uses the socket. 1182 * 1183 * @param observer Observer to add (implements Observer). 1184 */ 1185 virtual void addObserver(Observer* observer) = 0; 1186 1187 /** 1188 * Removes an observer. 1189 * 1190 * @param observer Observer to remove. 1191 * @return Whether observer found and removed from list. 1192 */ 1193 virtual bool removeObserver(Observer* observer) = 0; 1194 1195 /** 1196 * Returns installed observers. 1197 * 1198 * @return Reference to const vector with installed observers. 1199 */ 1200 FOLLY_NODISCARD virtual const ObserverVec& getObservers() const = 0; 1201 1202 /** 1203 * Returns varios stats of the connection. 1204 */ 1205 FOLLY_NODISCARD virtual QuicConnectionStats getConnectionsStats() const = 0; 1206 1207 /** 1208 * ===== Datagram API ===== 1209 * 1210 * Datagram support is experimental. Currently there isn't delivery callback 1211 * or loss notification support for Datagram. 1212 */ 1213 1214 class DatagramCallback { 1215 public: 1216 virtual ~DatagramCallback() = default; 1217 1218 /** 1219 * Notifies the DatagramCallback that datagrams are available for read. 1220 */ 1221 virtual void onDatagramsAvailable() noexcept = 0; 1222 }; 1223 1224 /** 1225 * Set the read callback for Datagrams 1226 */ 1227 virtual folly::Expected<folly::Unit, LocalErrorCode> setDatagramCallback( 1228 DatagramCallback* cb) = 0; 1229 1230 /** 1231 * Returns the maximum allowed Datagram payload size. 1232 * 0 means Datagram is not supported 1233 */ 1234 FOLLY_NODISCARD virtual uint16_t getDatagramSizeLimit() const = 0; 1235 1236 /** 1237 * Writes a Datagram frame. If buf is larger than the size limit returned by 1238 * getDatagramSizeLimit(), or if the write buffer is full, buf will simply be 1239 * dropped, and a LocalErrorCode will be returned to caller. 1240 */ 1241 virtual WriteResult writeDatagram(Buf buf) = 0; 1242 1243 /** 1244 * Returns the currently available received Datagrams. 1245 * Returns all datagrams if atMost is 0. 1246 */ 1247 virtual folly::Expected<std::vector<Buf>, LocalErrorCode> readDatagrams( 1248 size_t atMost = 0) = 0; 1249 }; 1250 } // namespace quic 1251