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