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 <folly/Optional.h>
12 
13 #include <folly/String.h>
14 #include <folly/hash/Hash.h>
15 #include <folly/io/Cursor.h>
16 #include <folly/io/IOBuf.h>
17 
18 #include <array>
19 
20 #include <quic/QuicConstants.h>
21 
22 namespace quic {
23 constexpr uint8_t kStatelessResetTokenLength = 16;
24 using StatelessResetToken = std::array<uint8_t, kStatelessResetTokenLength>;
25 
26 // max size of a connId as specified in the draft
27 constexpr size_t kMaxConnectionIdSize = 20;
28 
29 // Minimum required length (in bytes) for the destination connection-id
30 // on inbound initial packets.
31 constexpr size_t kMinInitialDestinationConnIdLength = 8;
32 
33 constexpr uint64_t kInitialSequenceNumber = 0x0;
34 
35 // First two bits of CID is version
36 enum class ConnectionIdVersion : uint8_t { V0 = 0, V1 = 1, V2 = 2, V3 = 3 };
37 
38 struct ConnectionId {
39   uint8_t* data();
40 
41   const uint8_t* data() const;
42 
43   uint8_t size() const;
44 
45   explicit ConnectionId(const std::vector<uint8_t>& connidIn);
46 
47   explicit ConnectionId(folly::io::Cursor& cursor, size_t len);
48 
49   bool operator==(const ConnectionId& other) const;
50   bool operator!=(const ConnectionId& other) const;
51 
52   std::string hex() const;
53 
54   /**
55    * Create an connection without any checks for tests.
56    */
57   static ConnectionId createWithoutChecks(const std::vector<uint8_t>& connidIn);
58 
59   /**
60    * Create a random ConnectionId with the given length.
61    */
62   static ConnectionId createRandom(size_t len);
63 
64  private:
65   ConnectionId() = default;
66 
67   std::array<uint8_t, kMaxConnectionIdSize> connid;
68   uint8_t connidLen;
69 };
70 
71 struct ConnectionIdHash {
operatorConnectionIdHash72   size_t operator()(const ConnectionId& connId) const {
73     return folly::hash::fnv32_buf(connId.data(), connId.size());
74   }
75 };
76 
77 inline std::ostream& operator<<(std::ostream& os, const ConnectionId& connId) {
78   os << connId.hex();
79   return os;
80 }
81 
toData(const ConnectionId & connId)82 inline folly::IOBuf toData(const ConnectionId& connId) {
83   return folly::IOBuf::wrapBufferAsValue(connId.data(), connId.size());
84 }
85 
86 struct ConnectionIdData {
ConnectionIdDataConnectionIdData87   ConnectionIdData(const ConnectionId& connIdIn, uint64_t sequenceNumberIn)
88       : connId(connIdIn), sequenceNumber(sequenceNumberIn) {}
89 
ConnectionIdDataConnectionIdData90   ConnectionIdData(
91       const ConnectionId& connIdIn,
92       uint64_t sequenceNumberIn,
93       StatelessResetToken tokenIn)
94       : connId(connIdIn), sequenceNumber(sequenceNumberIn), token(tokenIn) {}
95 
96   ConnectionId connId;
97   uint64_t sequenceNumber;
98   folly::Optional<StatelessResetToken> token;
99 };
100 
101 /**
102  * Encapsulate parameters to generate server chosen connection id
103  */
104 struct ServerConnectionIdParams {
ServerConnectionIdParamsServerConnectionIdParams105   explicit ServerConnectionIdParams(
106       uint32_t hostIdIn,
107       uint8_t processIdIn,
108       uint8_t workerIdIn)
109       : ServerConnectionIdParams(
110             ConnectionIdVersion::V1,
111             hostIdIn,
112             processIdIn,
113             workerIdIn) {}
114 
ServerConnectionIdParamsServerConnectionIdParams115   explicit ServerConnectionIdParams(
116       ConnectionIdVersion versionIn,
117       uint32_t hostIdIn,
118       uint8_t processIdIn,
119       uint8_t workerIdIn) {
120     setVersion(versionIn);
121     setHostId(hostIdIn);
122     setProcessId(processIdIn);
123     setWorkerId(workerIdIn);
124   }
125 
126   /**
127    * Set Quic connection-id short version
128    */
129   void setVersion(ConnectionIdVersion versionIn);
130 
131   /**
132    * Set Quic Host id
133    * Depending on version, lower 2 or 3 bytes used
134    */
135   void setHostId(uint32_t hostIdIn);
136 
137   /**
138    * Set Quic process id
139    */
140   void setProcessId(uint8_t processIdIn);
141 
142   /**
143    * Set Quic server worker Id
144    */
145   void setWorkerId(uint8_t workerIdIn);
146 
147   // Quic connection-id short version
148   ConnectionIdVersion version{ConnectionIdVersion::V0};
149   // Quic Host id
150   uint32_t hostId{0};
151   // Quic process id
152   uint8_t processId{0};
153   // Quic server worker Id
154   uint8_t workerId{0};
155 };
156 
157 bool operator==(
158     const ServerConnectionIdParams& lhs,
159     const ServerConnectionIdParams& rhs);
160 
161 bool operator!=(
162     const ServerConnectionIdParams& lhs,
163     const ServerConnectionIdParams& rhs);
164 
165 } // namespace quic
166