summaryrefslogtreecommitdiff
path: root/netwerk/protocol/http/Http2Push.h
blob: d4b71c1ef02f531e53628c9c4d7dc8e7f233a83c (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
142
143
144
145
146
147
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_net_Http2Push_Internal_h
#define mozilla_net_Http2Push_Internal_h

// HTTP/2 - RFC 7540
// https://www.rfc-editor.org/rfc/rfc7540.txt

#include "Http2Session.h"
#include "Http2Stream.h"

#include "mozilla/Attributes.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/UniquePtr.h"
#include "nsHttpRequestHead.h"
#include "nsILoadGroup.h"
#include "nsIRequestContext.h"
#include "nsString.h"
#include "PSpdyPush.h"

namespace mozilla {
namespace net {

class Http2PushTransactionBuffer;

class Http2PushedStream final : public Http2Stream
{
public:
  Http2PushedStream(Http2PushTransactionBuffer *aTransaction,
                    Http2Session *aSession,
                    Http2Stream *aAssociatedStream,
                    uint32_t aID);
  virtual ~Http2PushedStream() {}

  bool GetPushComplete();

  // The consumer stream is the synthetic pull stream hooked up to this push
  virtual Http2Stream *GetConsumerStream() override { return mConsumerStream; };

  void SetConsumerStream(Http2Stream *aStream);
  bool GetHashKey(nsCString &key);

  // override of Http2Stream
  nsresult ReadSegments(nsAHttpSegmentReader *,  uint32_t, uint32_t *) override;
  nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *) override;
  void AdjustInitialWindow() override;

  nsIRequestContext *RequestContext() override { return mRequestContext; };
  void ConnectPushedStream(Http2Stream *consumer);

  bool TryOnPush();
  static bool TestOnPush(Http2Stream *consumer);

  virtual bool DeferCleanup(nsresult status) override;
  void SetDeferCleanupOnSuccess(bool val) { mDeferCleanupOnSuccess = val; }

  bool IsOrphaned(TimeStamp now);
  void OnPushFailed() { mDeferCleanupOnPush = false; mOnPushFailed = true; }

  nsresult GetBufferedData(char *buf, uint32_t count, uint32_t *countWritten);

  // overload of Http2Stream
  virtual bool HasSink() override { return !!mConsumerStream; }

  nsCString &GetRequestString() { return mRequestString; }

private:

  Http2Stream *mConsumerStream; // paired request stream that consumes from
                                // real http/2 one.. null until a match is made.

  nsCOMPtr<nsIRequestContext> mRequestContext;

  nsAHttpTransaction *mAssociatedTransaction;

  Http2PushTransactionBuffer *mBufferedPush;
  mozilla::TimeStamp mLastRead;

  nsCString mHashKey;
  nsresult mStatus;
  bool mPushCompleted; // server push FIN received
  bool mDeferCleanupOnSuccess;

  // mDeferCleanupOnPush prevents Http2Session::CleanupStream() from
  // destroying the push stream on an error code during the period between
  // when we need to do OnPush() on another thread and the time it takes
  // for that event to create a synthetic pull stream attached to this
  // object. That synthetic pull will become mConsuemerStream.
  // Ths is essentially a delete protecting reference.
  bool mDeferCleanupOnPush;
  bool mOnPushFailed;
  nsCString mRequestString;

};

class Http2PushTransactionBuffer final : public nsAHttpTransaction
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSAHTTPTRANSACTION

  Http2PushTransactionBuffer();

  nsresult GetBufferedData(char *buf, uint32_t count, uint32_t *countWritten);
  void SetPushStream(Http2PushedStream *stream) { mPushStream = stream; }

private:
  virtual ~Http2PushTransactionBuffer();

  const static uint32_t kDefaultBufferSize = 4096;

  nsresult mStatus;
  nsHttpRequestHead *mRequestHead;
  Http2PushedStream *mPushStream;
  bool mIsDone;

  UniquePtr<char[]> mBufferedHTTP1;
  uint32_t mBufferedHTTP1Size;
  uint32_t mBufferedHTTP1Used;
  uint32_t mBufferedHTTP1Consumed;
};

class Http2PushedStreamWrapper : public nsISupports {
public:
  NS_DECL_THREADSAFE_ISUPPORTS
  bool DispatchRelease();

  explicit Http2PushedStreamWrapper(Http2PushedStream* aPushStream);

  nsCString& GetRequestString() { return mRequestString; }
  Http2PushedStream* GetStream();
  void OnPushFailed();

private:
  virtual ~Http2PushedStreamWrapper();

  nsCString mRequestString;
  WeakPtr<Http2Stream> mStream;
};

} // namespace net
} // namespace mozilla

#endif // mozilla_net_Http2Push_Internal_h