1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  *
7  */
8 
9 #pragma once
10 
11 #include <fizz/crypto/aead/Aead.h>
12 #include <fizz/record/Types.h>
13 #include <folly/Optional.h>
14 #include <folly/SocketAddress.h>
15 #include <quic/codec/QuicConnectionId.h>
16 #include <quic/codec/Types.h>
17 #include <quic/server/state/ServerStateMachine.h>
18 #include <quic/state/StateData.h>
19 
20 namespace quic {
21 
22 // TODO: I don't think i need client address here.
23 struct ConnKey {
24   ConnectionId scid;
25   ConnectionId dcid;
26 };
27 
28 struct ConnKeyHash {
operatorConnKeyHash29   std::size_t operator()(const ConnKey& key) const {
30     return folly::hash::hash_combine(
31         ConnectionIdHash()(key.scid), ConnectionIdHash()(key.dcid));
32   }
33 };
34 
35 struct ConnKeyEq {
operatorConnKeyEq36   bool operator()(const ConnKey& first, const ConnKey& second) const {
37     return first.scid == second.scid && first.dcid == second.dcid;
38   }
39 };
40 
41 /**
42  * The SendInstruction that frontend sends to backend to build a short-header
43  * QUIC packet that contains a single Stream Frame.
44  *
45  * For now, a DSR packet will only have one stream frame, and nothing else. So
46  * we are always gonna omit the Length field in the stream frame.
47  *
48  * TODO: Consider adding the type field here so that backend doesn't have to
49  * to calculate it.
50  *
51  * TODO: We can also send over the encoded QuicInteger of some of these values.
52  * Then the backends do not have to encode them again.
53  *
54  * TODO: Or even better: why don't I just send over the encoded short header
55  * and stream fields as well as the meta info?
56  */
57 
58 struct SendInstruction {
SendInstructionSendInstruction59   explicit SendInstruction(const SendInstruction& other)
60       : dcid(other.dcid),
61         scid(other.scid),
62         clientAddress(other.clientAddress),
63         packetNum(other.packetNum),
64         largestAckedPacketNum(other.largestAckedPacketNum),
65         streamId(other.streamId),
66         offset(other.offset),
67         len(other.len),
68         fin(other.fin),
69         bufMetaStartingOffset(other.bufMetaStartingOffset),
70         cipherSuite(other.cipherSuite),
71         packetProtectionKey(other.packetProtectionKey) {
72     if (other.trafficKey.key) {
73       trafficKey.key = other.trafficKey.key->clone();
74     }
75     if (other.trafficKey.iv) {
76       trafficKey.iv = other.trafficKey.iv->clone();
77     }
78   }
79 
SendInstructionSendInstruction80   explicit SendInstruction(SendInstruction&& other)
81       : dcid(other.dcid),
82         scid(other.scid),
83         clientAddress(other.clientAddress),
84         packetNum(other.packetNum),
85         largestAckedPacketNum(other.largestAckedPacketNum),
86         streamId(other.streamId),
87         offset(other.offset),
88         len(other.len),
89         fin(other.fin),
90         bufMetaStartingOffset(other.bufMetaStartingOffset),
91         trafficKey(std::move(other.trafficKey)),
92         cipherSuite(other.cipherSuite),
93         packetProtectionKey(other.packetProtectionKey) {}
94 
95   // Connection info:
96   const ConnectionId& dcid;
97   const ConnectionId& scid;
98   const folly::SocketAddress& clientAddress;
99   PacketNum packetNum{0};
100   PacketNum largestAckedPacketNum{0};
101 
102   // QUIC Stream info
103   StreamId streamId;
104   uint64_t offset;
105   uint64_t len;
106   bool fin;
107   uint64_t bufMetaStartingOffset;
108 
109   // Cipher info
110   TrafficKey trafficKey;
111   fizz::CipherSuite cipherSuite;
112   const Buf& packetProtectionKey;
113 
114   struct Builder {
BuilderSendInstruction::Builder115     explicit Builder(const QuicServerConnectionState& conn, StreamId idIn)
116         : dcid(*conn.clientConnectionId),
117           scid(*conn.serverConnectionId),
118           clientAddr(conn.peerAddress),
119           streamId(idIn),
120           trafficKey(*conn.oneRttWriteCipher->getKey()),
121           cipherSuite(*conn.serverHandshakeLayer->getState().cipher()),
122           packetProtectionKey(conn.oneRttWriteHeaderCipher->getKey()) {}
123 
buildSendInstruction::Builder124     SendInstruction build() {
125       return SendInstruction(
126           dcid,
127           scid,
128           clientAddr,
129           packetNum,
130           largestAckedPacketNum,
131           streamId,
132           *offset,
133           *len,
134           fin,
135           *bufMetaStartingOffset,
136           std::move(trafficKey),
137           cipherSuite,
138           packetProtectionKey);
139     }
140 
setPacketNumSendInstruction::Builder141     Builder& setPacketNum(PacketNum val) {
142       packetNum = val;
143       return *this;
144     }
145 
setLargestAckedPacketNumSendInstruction::Builder146     Builder& setLargestAckedPacketNum(PacketNum val) {
147       largestAckedPacketNum = val;
148       return *this;
149     }
150 
setOffsetSendInstruction::Builder151     Builder& setOffset(uint64_t val) {
152       offset = val;
153       return *this;
154     }
155 
setLengthSendInstruction::Builder156     Builder& setLength(uint64_t val) {
157       len = val;
158       return *this;
159     }
160 
setFinSendInstruction::Builder161     Builder& setFin(bool val) {
162       fin = val;
163       return *this;
164     }
165 
setBufMetaStartingOffsetSendInstruction::Builder166     Builder& setBufMetaStartingOffset(uint64_t val) {
167       bufMetaStartingOffset = val;
168       return *this;
169     }
170 
setTrafficKeySendInstruction::Builder171     Builder& setTrafficKey(TrafficKey val) {
172       trafficKey = std::move(val);
173       return *this;
174     }
175 
setCipherSuiteSendInstruction::Builder176     Builder& setCipherSuite(fizz::CipherSuite val) {
177       cipherSuite = val;
178       return *this;
179     }
180 
181    private:
182     const ConnectionId& dcid;
183     const ConnectionId& scid;
184     const folly::SocketAddress& clientAddr;
185     PacketNum packetNum{0};
186     PacketNum largestAckedPacketNum{0};
187     StreamId streamId;
188     folly::Optional<uint64_t> offset;
189     folly::Optional<uint64_t> len;
190     bool fin{false};
191     folly::Optional<uint64_t> bufMetaStartingOffset;
192     TrafficKey trafficKey;
193     fizz::CipherSuite cipherSuite;
194     const Buf& packetProtectionKey;
195   };
196 
197  private:
SendInstructionSendInstruction198   SendInstruction(
199       const ConnectionId& dcidIn,
200       const ConnectionId& scidIn,
201       const folly::SocketAddress& clientAddrIn,
202       PacketNum packetNumIn,
203       PacketNum largestAcked,
204       StreamId idIn,
205       uint64_t offsetIn,
206       uint64_t lenIn,
207       bool finIn,
208       uint64_t bufMetaStartingOffsetIn,
209       TrafficKey trafficKeyIn,
210       fizz::CipherSuite cipherSuiteIn,
211       const Buf& packetProtectionKeyIn)
212       : dcid(dcidIn),
213         scid(scidIn),
214         clientAddress(clientAddrIn),
215         packetNum(packetNumIn),
216         largestAckedPacketNum(largestAcked),
217         streamId(idIn),
218         offset(offsetIn),
219         len(lenIn),
220         fin(finIn),
221         bufMetaStartingOffset(bufMetaStartingOffsetIn),
222         trafficKey(std::move(trafficKeyIn)),
223         cipherSuite(cipherSuiteIn),
224         packetProtectionKey(packetProtectionKeyIn) {}
225 };
226 
227 WriteStreamFrame sendInstructionToWriteStreamFrame(
228     const SendInstruction& sendInstruction);
229 
230 } // namespace quic
231