| // Copyright (c) 2012 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_CORE_CRYPTO_CRYPTO_FRAMER_H_ |
| #define QUICHE_QUIC_CORE_CRYPTO_CRYPTO_FRAMER_H_ |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h" |
| #include "net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
| #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" |
| |
| namespace quic { |
| |
| class CryptoFramer; |
| class QuicData; |
| class QuicDataWriter; |
| |
| class QUIC_EXPORT_PRIVATE CryptoFramerVisitorInterface { |
| public: |
| virtual ~CryptoFramerVisitorInterface() {} |
| |
| // Called if an error is detected. |
| virtual void OnError(CryptoFramer* framer) = 0; |
| |
| // Called when a complete handshake message has been parsed. |
| virtual void OnHandshakeMessage(const CryptoHandshakeMessage& message) = 0; |
| }; |
| |
| // A class for framing the crypto messages that are exchanged in a QUIC |
| // session. |
| class QUIC_EXPORT_PRIVATE CryptoFramer : public CryptoMessageParser { |
| public: |
| CryptoFramer(); |
| |
| ~CryptoFramer() override; |
| |
| // ParseMessage parses exactly one message from the given |
| // quiche::QuicheStringPiece. If there is an error, the message is truncated, |
| // or the message has trailing garbage then nullptr will be returned. |
| static std::unique_ptr<CryptoHandshakeMessage> ParseMessage( |
| quiche::QuicheStringPiece in); |
| |
| // Set callbacks to be called from the framer. A visitor must be set, or |
| // else the framer will crash. It is acceptable for the visitor to do |
| // nothing. If this is called multiple times, only the last visitor |
| // will be used. |visitor| will be owned by the framer. |
| void set_visitor(CryptoFramerVisitorInterface* visitor) { |
| visitor_ = visitor; |
| } |
| |
| QuicErrorCode error() const override; |
| const std::string& error_detail() const override; |
| |
| // Processes input data, which must be delivered in order. Returns |
| // false if there was an error, and true otherwise. ProcessInput optionally |
| // takes an EncryptionLevel, but it is ignored. The variant with the |
| // EncryptionLevel is provided to match the CryptoMessageParser interface. |
| bool ProcessInput(quiche::QuicheStringPiece input, |
| EncryptionLevel level) override; |
| bool ProcessInput(quiche::QuicheStringPiece input); |
| |
| // Returns the number of bytes of buffered input data remaining to be |
| // parsed. |
| size_t InputBytesRemaining() const override; |
| |
| // Checks if the specified tag has been seen. Returns |true| if it |
| // has, and |false| if it has not or a CHLO has not been seen. |
| bool HasTag(QuicTag tag) const; |
| |
| // Even if the CHLO has not been fully received, force processing of |
| // the handshake message. This is dangerous and should not be used |
| // except as a mechanism of last resort. |
| void ForceHandshake(); |
| |
| // Returns a new QuicData owned by the caller that contains a serialized |
| // |message|, or nullptr if there was an error. |
| static std::unique_ptr<QuicData> ConstructHandshakeMessage( |
| const CryptoHandshakeMessage& message); |
| |
| // Debug only method which permits processing truncated messages. |
| void set_process_truncated_messages(bool process_truncated_messages) { |
| process_truncated_messages_ = process_truncated_messages; |
| } |
| |
| private: |
| // Clears per-message state. Does not clear the visitor. |
| void Clear(); |
| |
| // Process does does the work of |ProcessInput|, but returns an error code, |
| // doesn't set error_ and doesn't call |visitor_->OnError()|. |
| QuicErrorCode Process(quiche::QuicheStringPiece input); |
| |
| static bool WritePadTag(QuicDataWriter* writer, |
| size_t pad_length, |
| uint32_t* end_offset); |
| |
| // Represents the current state of the parsing state machine. |
| enum CryptoFramerState { |
| STATE_READING_TAG, |
| STATE_READING_NUM_ENTRIES, |
| STATE_READING_TAGS_AND_LENGTHS, |
| STATE_READING_VALUES |
| }; |
| |
| // Visitor to invoke when messages are parsed. |
| CryptoFramerVisitorInterface* visitor_; |
| // Last error. |
| QuicErrorCode error_; |
| // Remaining unparsed data. |
| std::string buffer_; |
| // Current state of the parsing. |
| CryptoFramerState state_; |
| // The message currently being parsed. |
| CryptoHandshakeMessage message_; |
| // The issue which caused |error_| |
| std::string error_detail_; |
| // Number of entires in the message currently being parsed. |
| uint16_t num_entries_; |
| // tags_and_lengths_ contains the tags that are currently being parsed and |
| // their lengths. |
| std::vector<std::pair<QuicTag, size_t>> tags_and_lengths_; |
| // Cumulative length of all values in the message currently being parsed. |
| size_t values_len_; |
| // Set to true to allow of processing of truncated messages for debugging. |
| bool process_truncated_messages_; |
| }; |
| |
| } // namespace quic |
| |
| #endif // QUICHE_QUIC_CORE_CRYPTO_CRYPTO_FRAMER_H_ |