blob: a74e3b1ec0cbc2b46f21038bb4d7c93ae2e9fbda [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
6
7#include <cstdint>
8#include <cstring>
9#include <iomanip>
vasilvv872e7a32019-03-12 16:42:44 -070010#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
12#include "net/third_party/quiche/src/quic/core/quic_types.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050018#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
19
20namespace quic {
21
dschinazib3241162019-06-10 17:59:37 -070022QuicConnectionId::QuicConnectionId() : QuicConnectionId(nullptr, 0) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050023
24QuicConnectionId::QuicConnectionId(const char* data, uint8_t length) {
dschinazib3241162019-06-10 17:59:37 -070025 static_assert(
26 kQuicMaxConnectionIdLength <= std::numeric_limits<uint8_t>::max(),
27 "kQuicMaxConnectionIdLength too high");
QUICHE teama6ef0a62019-03-07 20:34:33 -050028 if (length > kQuicMaxConnectionIdLength) {
29 QUIC_BUG << "Attempted to create connection ID of length " << length;
30 length = kQuicMaxConnectionIdLength;
31 }
32 length_ = length;
dschinazib3241162019-06-10 17:59:37 -070033 if (length_ == 0) {
34 return;
35 }
36 if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050037 memcpy(data_, data, length_);
dschinazib3241162019-06-10 17:59:37 -070038 return;
39 }
dschinazi6abd56b2019-06-18 18:04:30 -070040 QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 1, 6);
dschinazib3241162019-06-10 17:59:37 -070041 if (length_ <= sizeof(data_short_)) {
42 memcpy(data_short_, data, length_);
43 return;
44 }
45 data_long_ = reinterpret_cast<char*>(malloc(length_));
46 CHECK_NE(nullptr, data_long_);
47 memcpy(data_long_, data, length_);
48}
49
50QuicConnectionId::~QuicConnectionId() {
51 if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
52 return;
53 }
dschinazi6abd56b2019-06-18 18:04:30 -070054 QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 2, 6);
dschinazib3241162019-06-10 17:59:37 -070055 if (length_ > sizeof(data_short_)) {
56 free(data_long_);
57 data_long_ = nullptr;
QUICHE teama6ef0a62019-03-07 20:34:33 -050058 }
59}
60
dschinazib3241162019-06-10 17:59:37 -070061QuicConnectionId::QuicConnectionId(const QuicConnectionId& other)
62 : QuicConnectionId(other.data(), other.length()) {}
63
64QuicConnectionId& QuicConnectionId::operator=(const QuicConnectionId& other) {
65 set_length(other.length());
66 memcpy(mutable_data(), other.data(), length_);
67 return *this;
68}
QUICHE teama6ef0a62019-03-07 20:34:33 -050069
70const char* QuicConnectionId::data() const {
dschinazib3241162019-06-10 17:59:37 -070071 if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
72 return data_;
73 }
dschinazi6abd56b2019-06-18 18:04:30 -070074 QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 3, 6);
dschinazib3241162019-06-10 17:59:37 -070075 if (length_ <= sizeof(data_short_)) {
76 return data_short_;
77 }
78 return data_long_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050079}
80
81char* QuicConnectionId::mutable_data() {
dschinazib3241162019-06-10 17:59:37 -070082 if (!GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
83 return data_;
84 }
dschinazi6abd56b2019-06-18 18:04:30 -070085 QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 4, 6);
dschinazib3241162019-06-10 17:59:37 -070086 if (length_ <= sizeof(data_short_)) {
87 return data_short_;
88 }
89 return data_long_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050090}
91
92uint8_t QuicConnectionId::length() const {
93 return length_;
94}
95
96void QuicConnectionId::set_length(uint8_t length) {
dschinazib3241162019-06-10 17:59:37 -070097 if (GetQuicRestartFlag(quic_use_allocated_connection_ids)) {
dschinazi6abd56b2019-06-18 18:04:30 -070098 QUIC_RESTART_FLAG_COUNT_N(quic_use_allocated_connection_ids, 5, 6);
dschinazib3241162019-06-10 17:59:37 -070099 char temporary_data[sizeof(data_short_)];
100 if (length > sizeof(data_short_)) {
101 if (length_ <= sizeof(data_short_)) {
102 // Copy data from data_short_ to data_long_.
103 memcpy(temporary_data, data_short_, length_);
104 data_long_ = reinterpret_cast<char*>(malloc(length));
105 CHECK_NE(nullptr, data_long_);
106 memcpy(data_long_, temporary_data, length_);
107 } else {
108 // Resize data_long_.
109 char* realloc_result =
110 reinterpret_cast<char*>(realloc(data_long_, length));
111 CHECK_NE(nullptr, realloc_result);
112 data_long_ = realloc_result;
113 }
114 } else if (length_ > sizeof(data_short_)) {
115 // Copy data from data_long_ to data_short_.
116 memcpy(temporary_data, data_long_, length);
117 free(data_long_);
118 data_long_ = nullptr;
119 memcpy(data_short_, temporary_data, length);
120 }
121 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122 length_ = length;
123}
124
125bool QuicConnectionId::IsEmpty() const {
126 return length_ == 0;
127}
128
129size_t QuicConnectionId::Hash() const {
130 uint64_t data_bytes[3] = {0, 0, 0};
dschinazib3241162019-06-10 17:59:37 -0700131 static_assert(sizeof(data_bytes) >= kQuicMaxConnectionIdLength,
132 "kQuicMaxConnectionIdLength changed");
133 memcpy(data_bytes, data(), length_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134 // This Hash function is designed to return the same value as the host byte
135 // order representation when the connection ID length is 64 bits.
136 return QuicEndian::NetToHost64(kQuicDefaultConnectionIdLength ^ length_ ^
137 data_bytes[0] ^ data_bytes[1] ^ data_bytes[2]);
138}
139
vasilvvc48c8712019-03-11 13:38:16 -0700140std::string QuicConnectionId::ToString() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 if (IsEmpty()) {
vasilvvc48c8712019-03-11 13:38:16 -0700142 return std::string("0");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500143 }
dschinazib3241162019-06-10 17:59:37 -0700144 return QuicTextUtils::HexEncode(data(), length_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145}
146
147std::ostream& operator<<(std::ostream& os, const QuicConnectionId& v) {
148 os << v.ToString();
149 return os;
150}
151
152bool QuicConnectionId::operator==(const QuicConnectionId& v) const {
dschinazib3241162019-06-10 17:59:37 -0700153 return length_ == v.length_ && memcmp(data(), v.data(), length_) == 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154}
155
156bool QuicConnectionId::operator!=(const QuicConnectionId& v) const {
157 return !(v == *this);
158}
159
160bool QuicConnectionId::operator<(const QuicConnectionId& v) const {
161 if (length_ < v.length_) {
162 return true;
163 }
164 if (length_ > v.length_) {
165 return false;
166 }
dschinazib3241162019-06-10 17:59:37 -0700167 return memcmp(data(), v.data(), length_) < 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500168}
169
170QuicConnectionId EmptyQuicConnectionId() {
171 return QuicConnectionId();
172}
173
174static_assert(kQuicDefaultConnectionIdLength == sizeof(uint64_t),
175 "kQuicDefaultConnectionIdLength changed");
176static_assert(kQuicDefaultConnectionIdLength == PACKET_8BYTE_CONNECTION_ID,
177 "kQuicDefaultConnectionIdLength changed");
178
179} // namespace quic