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 #include <quic/state/StateData.h>
10 
11 #include <quic/state/QuicStreamUtilities.h>
12 
13 namespace quic {
QuicStreamState(StreamId idIn,QuicConnectionStateBase & connIn)14 QuicStreamState::QuicStreamState(StreamId idIn, QuicConnectionStateBase& connIn)
15     : conn(connIn), id(idIn) {
16   // Note: this will set a windowSize for a locally-initiated unidirectional
17   // stream even though that value is meaningless.
18   flowControlState.windowSize = isUnidirectionalStream(idIn)
19       ? conn.transportSettings.advertisedInitialUniStreamWindowSize
20       : isLocalStream(connIn.nodeType, idIn)
21       ? conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize
22       : conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize;
23   flowControlState.advertisedMaxOffset = isUnidirectionalStream(idIn)
24       ? conn.transportSettings.advertisedInitialUniStreamWindowSize
25       : isLocalStream(connIn.nodeType, idIn)
26       ? conn.transportSettings.advertisedInitialBidiLocalStreamWindowSize
27       : conn.transportSettings.advertisedInitialBidiRemoteStreamWindowSize;
28   // Note: this will set a peerAdvertisedMaxOffset for a peer-initiated
29   // unidirectional stream even though that value is meaningless.
30   flowControlState.peerAdvertisedMaxOffset = isUnidirectionalStream(idIn)
31       ? conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetUni
32       : isLocalStream(connIn.nodeType, idIn)
33       ? conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote
34       : conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal;
35   if (isUnidirectionalStream(idIn)) {
36     if (isLocalStream(connIn.nodeType, idIn)) {
37       recvState = StreamRecvState::Invalid;
38     } else {
39       sendState = StreamSendState::Invalid;
40     }
41   }
42 }
43 
operator <<(std::ostream & os,const QuicConnectionStateBase & st)44 std::ostream& operator<<(std::ostream& os, const QuicConnectionStateBase& st) {
45   if (st.clientConnectionId) {
46     os << "client CID=" << *st.clientConnectionId;
47   } else {
48     os << "client CID=None";
49   }
50   if (st.serverConnectionId) {
51     os << " server CID=" << *st.serverConnectionId;
52   } else {
53     os << " server CID=None";
54   }
55   os << " peer address=" << st.peerAddress;
56   return os;
57 }
58 
AckStateVersion(uint64_t initialVersion,uint64_t handshakeVersion,uint64_t appDataVersion)59 AckStateVersion::AckStateVersion(
60     uint64_t initialVersion,
61     uint64_t handshakeVersion,
62     uint64_t appDataVersion)
63     : initialAckStateVersion(initialVersion),
64       handshakeAckStateVersion(handshakeVersion),
65       appDataAckStateVersion(appDataVersion) {}
66 
operator ==(const AckStateVersion & other) const67 bool AckStateVersion::operator==(const AckStateVersion& other) const {
68   return initialAckStateVersion == other.initialAckStateVersion &&
69       handshakeAckStateVersion == other.handshakeAckStateVersion &&
70       appDataAckStateVersion == other.appDataAckStateVersion;
71 }
72 
operator !=(const AckStateVersion & other) const73 bool AckStateVersion::operator!=(const AckStateVersion& other) const {
74   return !operator==(other);
75 }
76 
PacingRate(std::chrono::microseconds intervalIn,uint64_t burstSizeIn)77 PacingRate::PacingRate(
78     std::chrono::microseconds intervalIn,
79     uint64_t burstSizeIn)
80     : interval(intervalIn), burstSize(burstSizeIn) {}
81 
setInterval(std::chrono::microseconds intervalIn)82 PacingRate::Builder&& PacingRate::Builder::setInterval(
83     std::chrono::microseconds intervalIn) && {
84   interval_ = intervalIn;
85   return std::move(*this);
86 }
87 
setBurstSize(uint64_t burstSizeIn)88 PacingRate::Builder&& PacingRate::Builder::setBurstSize(
89     uint64_t burstSizeIn) && {
90   burstSize_ = burstSizeIn;
91   return std::move(*this);
92 }
93 
build()94 PacingRate PacingRate::Builder::build() && {
95   return PacingRate(interval_, burstSize_);
96 }
97 
AckPacket(TimePoint sentTimeIn,uint32_t encodedSizeIn,folly::Optional<OutstandingPacket::LastAckedPacketInfo> lastAckedPacketInfoIn,uint64_t totalBytesSentThenIn,bool isAppLimitedIn)98 CongestionController::AckEvent::AckPacket::AckPacket(
99     TimePoint sentTimeIn,
100     uint32_t encodedSizeIn,
101     folly::Optional<OutstandingPacket::LastAckedPacketInfo>
102         lastAckedPacketInfoIn,
103     uint64_t totalBytesSentThenIn,
104     bool isAppLimitedIn)
105     : sentTime(sentTimeIn),
106       encodedSize(encodedSizeIn),
107       lastAckedPacketInfo(std::move(lastAckedPacketInfoIn)),
108       totalBytesSentThen(totalBytesSentThenIn),
109       isAppLimited(isAppLimitedIn) {}
110 
111 CongestionController::AckEvent::AckPacket::Builder&&
setSentTime(TimePoint sentTimeIn)112 CongestionController::AckEvent::AckPacket::Builder::setSentTime(
113     TimePoint sentTimeIn) {
114   sentTime = sentTimeIn;
115   return std::move(*this);
116 }
117 
118 CongestionController::AckEvent::AckPacket::Builder&&
setEncodedSize(uint32_t encodedSizeIn)119 CongestionController::AckEvent::AckPacket::Builder::setEncodedSize(
120     uint32_t encodedSizeIn) {
121   encodedSize = encodedSizeIn;
122   return std::move(*this);
123 }
124 
125 CongestionController::AckEvent::AckPacket::Builder&&
setLastAckedPacketInfo(folly::Optional<OutstandingPacket::LastAckedPacketInfo> lastAckedPacketInfoIn)126 CongestionController::AckEvent::AckPacket::Builder::setLastAckedPacketInfo(
127     folly::Optional<OutstandingPacket::LastAckedPacketInfo>
128         lastAckedPacketInfoIn) {
129   lastAckedPacketInfo = lastAckedPacketInfoIn;
130   return std::move(*this);
131 }
132 
133 CongestionController::AckEvent::AckPacket::Builder&&
setTotalBytesSentThen(uint64_t totalBytesSentThenIn)134 CongestionController::AckEvent::AckPacket::Builder::setTotalBytesSentThen(
135     uint64_t totalBytesSentThenIn) {
136   totalBytesSentThen = totalBytesSentThenIn;
137   return std::move(*this);
138 }
139 
140 CongestionController::AckEvent::AckPacket::Builder&&
setAppLimited(bool appLimitedIn)141 CongestionController::AckEvent::AckPacket::Builder::setAppLimited(
142     bool appLimitedIn) {
143   isAppLimited = appLimitedIn;
144   return std::move(*this);
145 }
146 
147 CongestionController::AckEvent::AckPacket
build()148 CongestionController::AckEvent::AckPacket::Builder::build() && {
149   return CongestionController::AckEvent::AckPacket(
150       sentTime,
151       encodedSize,
152       std::move(lastAckedPacketInfo),
153       totalBytesSentThen,
154       isAppLimited);
155 }
156 
retireAndSwitchPeerConnectionIds()157 bool QuicConnectionStateBase::retireAndSwitchPeerConnectionIds() {
158   const auto end = peerConnectionIds.end();
159   auto replacementConnIdDataIt{end};
160   auto currentConnIdDataIt{end};
161 
162   auto& mainPeerId = nodeType == QuicNodeType::Client ? serverConnectionId
163                                                       : clientConnectionId;
164   if (!mainPeerId) {
165     throw QuicTransportException(
166         "Attempting to retire null peer conn id",
167         TransportErrorCode::INTERNAL_ERROR);
168   }
169 
170   // Retrieve the sequence number of the current cId, and find an unused
171   // ConnectionIdData.
172   for (auto it = peerConnectionIds.begin(); it != end; it++) {
173     if (replacementConnIdDataIt != end && currentConnIdDataIt != end) {
174       break;
175     }
176 
177     if (it->connId == mainPeerId) {
178       currentConnIdDataIt = it;
179     } else if (replacementConnIdDataIt == end) {
180       replacementConnIdDataIt = it;
181     }
182   }
183   if (replacementConnIdDataIt == end) {
184     return false;
185   }
186   DCHECK(currentConnIdDataIt != end);
187   pendingEvents.frames.push_back(
188       RetireConnectionIdFrame(currentConnIdDataIt->sequenceNumber));
189   mainPeerId = replacementConnIdDataIt->connId;
190 
191   peerConnectionIds.erase(currentConnIdDataIt);
192   return true;
193 }
194 
195 } // namespace quic
196