| // Copyright 2019 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef QUICHE_QUIC_MASQUE_MASQUE_PROTOCOL_H_ | 
 | #define QUICHE_QUIC_MASQUE_MASQUE_PROTOCOL_H_ | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "quic/core/quic_connection_id.h" | 
 | #include "quic/core/quic_session.h" | 
 | #include "quic/core/quic_types.h" | 
 | #include "quic/platform/api/quic_containers.h" | 
 | #include "quic/platform/api/quic_export.h" | 
 | #include "quic/platform/api/quic_socket_address.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | // MASQUE compression engine used by client and servers. | 
 | // This class allows converting QUIC packets into a compressed form suitable | 
 | // for sending over QUIC DATAGRAM frames. It leverages a flow identifier at the | 
 | // start of each datagram to indicate which compression context was used to | 
 | // compress this packet, or to create new compression contexts. | 
 | // Compression contexts contain client and server connection IDs and the | 
 | // server's IP and port. This allows compressing that information in most | 
 | // packets without requiring access to the cryptographic keys of the end-to-end | 
 | // encapsulated session. When the flow identifier is 0, the DATAGRAM contains | 
 | // all the contents of the compression context. When the flow identifier is | 
 | // non-zero, those fields are removed so the encapsulated QUIC packet is | 
 | // transmitted without connection IDs and reassembled by the peer on | 
 | // decompression. This only needs to contain the HTTP server's IP address since | 
 | // the client's IP address is not visible to the HTTP server. | 
 |  | 
 | class QUIC_NO_EXPORT MasqueCompressionEngine { | 
 |  public: | 
 |   // Caller must ensure that |masque_session| has a lifetime longer than the | 
 |   // newly constructed MasqueCompressionEngine. | 
 |   explicit MasqueCompressionEngine(QuicSession* masque_session); | 
 |  | 
 |   // Disallow copy and assign. | 
 |   MasqueCompressionEngine(const MasqueCompressionEngine&) = delete; | 
 |   MasqueCompressionEngine& operator=(const MasqueCompressionEngine&) = delete; | 
 |  | 
 |   // Compresses packet and sends it in a DATAGRAM frame over a MASQUE session. | 
 |   // When used from MASQUE client to MASQUE server, the MASQUE server will then | 
 |   // send the packet to the provided |server_address|. | 
 |   // When used from MASQUE server to MASQUE client, the MASQUE client will then | 
 |   // hand off the uncompressed packet to an encapsulated session that will treat | 
 |   // it as having come from the provided |server_address|. | 
 |   // The connection IDs are the one used by the encapsulated |packet|. | 
 |   void CompressAndSendPacket(absl::string_view packet, | 
 |                              QuicConnectionId client_connection_id, | 
 |                              QuicConnectionId server_connection_id, | 
 |                              const QuicSocketAddress& server_address); | 
 |  | 
 |   // Decompresses received DATAGRAM frame contents from |datagram| and places | 
 |   // them in |packet|. Reverses the transformation from CompressAndSendPacket. | 
 |   // The connection IDs are the one used by the encapsulated |packet|. | 
 |   // |server_address| will be filled with the |server_address| passed to | 
 |   // CompressAndSendPacket. |version_present| will contain whether the | 
 |   // encapsulated |packet| contains a Version field. | 
 |   bool DecompressDatagram(absl::string_view datagram, | 
 |                           QuicConnectionId* client_connection_id, | 
 |                           QuicConnectionId* server_connection_id, | 
 |                           QuicSocketAddress* server_address, | 
 |                           std::vector<char>* packet, | 
 |                           bool* version_present); | 
 |  | 
 |   // Clears all entries referencing |client_connection_id| from the | 
 |   // compression table. | 
 |   void UnregisterClientConnectionId(QuicConnectionId client_connection_id); | 
 |  | 
 |  private: | 
 |   struct QUIC_NO_EXPORT MasqueCompressionContext { | 
 |     QuicConnectionId client_connection_id; | 
 |     QuicConnectionId server_connection_id; | 
 |     QuicSocketAddress server_address; | 
 |     bool validated = false; | 
 |   }; | 
 |  | 
 |   // Generates a new datagram flow ID. | 
 |   QuicDatagramFlowId GetNextFlowId(); | 
 |  | 
 |   // Finds or creates a new compression context to use during compression. | 
 |   // |client_connection_id_present| and |server_connection_id_present| indicate | 
 |   // whether the corresponding connection ID is present in the current packet. | 
 |   // |validated| will contain whether the compression context that matches | 
 |   // these arguments is currently validated or not. | 
 |   QuicDatagramFlowId FindOrCreateCompressionContext( | 
 |       QuicConnectionId client_connection_id, | 
 |       QuicConnectionId server_connection_id, | 
 |       const QuicSocketAddress& server_address, | 
 |       bool client_connection_id_present, | 
 |       bool server_connection_id_present, | 
 |       bool* validated); | 
 |  | 
 |   // Writes compressed packet to |slice| during compression. | 
 |   bool WriteCompressedPacketToSlice(QuicConnectionId client_connection_id, | 
 |                                     QuicConnectionId server_connection_id, | 
 |                                     const QuicSocketAddress& server_address, | 
 |                                     QuicConnectionId destination_connection_id, | 
 |                                     QuicConnectionId source_connection_id, | 
 |                                     QuicDatagramFlowId flow_id, | 
 |                                     bool validated, | 
 |                                     uint8_t first_byte, | 
 |                                     bool long_header, | 
 |                                     QuicDataReader* reader, | 
 |                                     QuicDataWriter* writer); | 
 |  | 
 |   // Parses compression context from flow ID 0 during decompression. | 
 |   bool ParseCompressionContext(QuicDataReader* reader, | 
 |                                MasqueCompressionContext* context); | 
 |  | 
 |   // Writes decompressed packet to |packet| during decompression. | 
 |   bool WriteDecompressedPacket(QuicDataReader* reader, | 
 |                                const MasqueCompressionContext& context, | 
 |                                std::vector<char>* packet, | 
 |                                bool* version_present); | 
 |  | 
 |   QuicSession* masque_session_;  // Unowned. | 
 |   QuicHashMap<QuicDatagramFlowId, MasqueCompressionContext> contexts_; | 
 |   QuicDatagramFlowId next_flow_id_; | 
 | }; | 
 |  | 
 | }  // namespace quic | 
 |  | 
 | #endif  // QUICHE_QUIC_MASQUE_MASQUE_PROTOCOL_H_ |