1 // Copyright 2023 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_QUIC_TOOLS_DEVIOUS_BATON_H_ 6 #define QUICHE_QUIC_TOOLS_DEVIOUS_BATON_H_ 7 8 #include "quiche/common/quiche_callbacks.h" 9 #include "quiche/common/quiche_circular_deque.h" 10 #include "quiche/web_transport/web_transport.h" 11 12 namespace quic { 13 14 // https://www.ietf.org/id/draft-frindell-webtrans-devious-baton-00.html#name-session-error-codes 15 inline constexpr webtransport::SessionErrorCode kDeviousBatonErrorDaYamn = 16 0x01; // Insufficient flow control credit 17 inline constexpr webtransport::SessionErrorCode kDeviousBatonErrorBruh = 18 0x02; // Parse error 19 inline constexpr webtransport::SessionErrorCode kDeviousBatonErrorSus = 20 0x03; // Unexpected message 21 inline constexpr webtransport::SessionErrorCode kDeviousBatonErrorBored = 22 0x04; // Timeout 23 24 using DeviousBatonValue = uint8_t; 25 26 // Implementation of the Devious Baton protocol as described in 27 // https://www.ietf.org/id/draft-frindell-webtrans-devious-baton-00.html 28 class DeviousBatonSessionVisitor : public webtransport::SessionVisitor { 29 public: DeviousBatonSessionVisitor(webtransport::Session * session,bool is_server,int initial_value,int count)30 DeviousBatonSessionVisitor(webtransport::Session* session, bool is_server, 31 int initial_value, int count) 32 : session_(session), 33 is_server_(is_server), 34 initial_value_(initial_value), 35 count_(count) {} 36 37 void OnSessionReady() override; 38 void OnSessionClosed(webtransport::SessionErrorCode error_code, 39 const std::string& error_message) override; 40 void OnIncomingBidirectionalStreamAvailable() override; 41 void OnIncomingUnidirectionalStreamAvailable() override; 42 void OnDatagramReceived(absl::string_view datagram) override; 43 void OnCanCreateNewOutgoingBidirectionalStream() override; 44 void OnCanCreateNewOutgoingUnidirectionalStream() override; 45 46 private: 47 using SendFunction = void (DeviousBatonSessionVisitor::*)(DeviousBatonValue); SendUnidirectionalBaton(DeviousBatonValue value)48 void SendUnidirectionalBaton(DeviousBatonValue value) { 49 outgoing_unidi_batons_.push_back(value); 50 OnCanCreateNewOutgoingUnidirectionalStream(); 51 } SendBidirectionalBaton(DeviousBatonValue value)52 void SendBidirectionalBaton(DeviousBatonValue value) { 53 outgoing_bidi_batons_.push_back(value); 54 OnCanCreateNewOutgoingBidirectionalStream(); 55 } 56 57 // Creates a callback that parses an incoming baton, parses it (while 58 // potentially handling parse errors), and then passes it into the 59 // `send_function`. 60 quiche::SingleUseCallback<void(std::string)> CreateResponseCallback( 61 SendFunction send_function); 62 63 webtransport::Session* session_; 64 bool is_server_; 65 DeviousBatonValue initial_value_; 66 int count_; 67 quiche::QuicheCircularDeque<DeviousBatonValue> outgoing_unidi_batons_; 68 quiche::QuicheCircularDeque<DeviousBatonValue> outgoing_bidi_batons_; 69 }; 70 71 } // namespace quic 72 73 #endif // QUICHE_QUIC_TOOLS_DEVIOUS_BATON_H_ 74