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