summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h
blob: b0bc28b70027d59112da1d23006ed44090d36f78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_
#define QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_

#include <list>

#include "http2/adapter/http2_session.h"
#include "http2/adapter/http2_util.h"
#include "http2/adapter/http2_visitor_interface.h"
#include "http2/adapter/window_manager.h"
#include "common/platform/api/quiche_bug_tracker.h"
#include "spdy/core/http2_frame_decoder_adapter.h"
#include "spdy/core/spdy_framer.h"

namespace http2 {
namespace adapter {

// This class manages state associated with a single multiplexed HTTP/2 session.
class OgHttp2Session : public Http2Session,
                       public spdy::SpdyFramerVisitorInterface {
 public:
  struct Options {
    Perspective perspective = Perspective::kClient;
  };

  OgHttp2Session(Http2VisitorInterface& visitor, Options /*options*/);
  ~OgHttp2Session() override;

  // Enqueues a frame for transmission to the peer.
  void EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame);

  // If |want_write()| returns true, this method will return a non-empty string
  // containing serialized HTTP/2 frames to write to the peer.
  std::string GetBytesToWrite(absl::optional<size_t> max_bytes);

  // From Http2Session.
  ssize_t ProcessBytes(absl::string_view bytes) override;
  int Consume(Http2StreamId stream_id, size_t num_bytes) override;
  bool want_read() const override { return !received_goaway_; }
  bool want_write() const override {
    return !frames_.empty() || !serialized_prefix_.empty();
  }
  int GetRemoteWindowSize() const override {
    return peer_window_;
  }

  // From SpdyFramerVisitorInterface
  void OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
               std::string detailed_error) override;
  void OnCommonHeader(spdy::SpdyStreamId /*stream_id*/,
                      size_t /*length*/,
                      uint8_t /*type*/,
                      uint8_t /*flags*/) override;
  void OnDataFrameHeader(spdy::SpdyStreamId stream_id,
                         size_t length,
                         bool fin) override;
  void OnStreamFrameData(spdy::SpdyStreamId stream_id,
                         const char* data,
                         size_t len) override;
  void OnStreamEnd(spdy::SpdyStreamId stream_id) override;
  void OnStreamPadLength(spdy::SpdyStreamId /*stream_id*/,
                         size_t /*value*/) override;
  void OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) override;
  spdy::SpdyHeadersHandlerInterface* OnHeaderFrameStart(
      spdy::SpdyStreamId stream_id) override;
  void OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) override;
  void OnRstStream(spdy::SpdyStreamId stream_id,
                   spdy::SpdyErrorCode error_code) override;
  void OnSettings() override;
  void OnSetting(spdy::SpdySettingsId id, uint32_t value) override;
  void OnSettingsEnd() override;
  void OnSettingsAck() override;
  void OnPing(spdy::SpdyPingId unique_id, bool is_ack) override;
  void OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
                spdy::SpdyErrorCode error_code) override;
  bool OnGoAwayFrameData(const char* goaway_data, size_t len);
  void OnHeaders(spdy::SpdyStreamId stream_id,
                 bool has_priority,
                 int weight,
                 spdy::SpdyStreamId parent_stream_id,
                 bool exclusive,
                 bool fin,
                 bool end) override;
  void OnWindowUpdate(spdy::SpdyStreamId stream_id,
                      int delta_window_size) override;
  void OnPushPromise(spdy::SpdyStreamId stream_id,
                     spdy::SpdyStreamId promised_stream_id,
                     bool end) override;
  void OnContinuation(spdy::SpdyStreamId stream_id, bool end) override;
  void OnAltSvc(spdy::SpdyStreamId /*stream_id*/,
                absl::string_view /*origin*/,
                const spdy::SpdyAltSvcWireFormat::
                    AlternativeServiceVector& /*altsvc_vector*/);
  void OnPriority(spdy::SpdyStreamId stream_id,
                  spdy::SpdyStreamId parent_stream_id,
                  int weight,
                  bool exclusive) override;
  void OnPriorityUpdate(spdy::SpdyStreamId prioritized_stream_id,
                        absl::string_view priority_field_value) override;
  bool OnUnknownFrame(spdy::SpdyStreamId stream_id,
                      uint8_t frame_type) override;

 private:
  struct StreamState {
    WindowManager window_manager;
    int32_t send_window = 65535;
    bool half_closed_local = false;
    bool half_closed_remote = false;
  };

  class PassthroughHeadersHandler : public spdy::SpdyHeadersHandlerInterface {
   public:
    explicit PassthroughHeadersHandler(Http2VisitorInterface& visitor)
        : visitor_(visitor) {}
    void set_stream_id(Http2StreamId stream_id) { stream_id_ = stream_id; }
    void OnHeaderBlockStart() override;
    void OnHeader(absl::string_view key, absl::string_view value) override;
    void OnHeaderBlockEnd(size_t /* uncompressed_header_bytes */,
                          size_t /* compressed_header_bytes */) override;

   private:
    Http2VisitorInterface& visitor_;
    Http2StreamId stream_id_ = 0;
  };

  Http2VisitorInterface& visitor_;
  spdy::SpdyFramer framer_{spdy::SpdyFramer::ENABLE_COMPRESSION};
  http2::Http2DecoderAdapter decoder_;
  absl::flat_hash_map<Http2StreamId, StreamState> stream_map_;
  std::list<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
  PassthroughHeadersHandler headers_handler_;
  std::string serialized_prefix_;
  absl::string_view remaining_preface_;
  int peer_window_ = 65535;
  Options options_;
  bool received_goaway_ = false;
};

}  // namespace adapter
}  // namespace http2

#endif  // QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_