Skip to content

Commit 5168fc6

Browse files
committed
Tear down old path after migration
1 parent 76d7587 commit 5168fc6

2 files changed

Lines changed: 40 additions & 10 deletions

File tree

Sources/SwiftNetwork/QUIC/Migration.swift

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct Migration: ~Copyable {
106106
return
107107
}
108108

109+
let oldPath = connection.currentPath
109110
connection.log.notice("Migrating to path \(path.identifier)")
110111
connection.currentPath = path
111112
path.spinValue = connection.initialSpinValue
@@ -128,6 +129,10 @@ struct Migration: ~Copyable {
128129
}
129130
// TODO: Handle preferred address migration
130131

132+
// Remove the path we just migrated away from.
133+
if let oldPath, oldPath != path {
134+
connection.tearDownMigratedPath(oldPath)
135+
}
131136
}
132137

133138
func probingPathCount(_ connection: QUICConnection) -> Int {
@@ -197,16 +202,7 @@ extension QUICConnection {
197202
}
198203
break
199204
case .unavailable:
200-
if path.isOpenForSending, let dcid = path.dcid,
201-
let sequence = remoteCIDs.retire(connectionID: dcid)
202-
{
203-
withPendingItems(
204-
for: .applicationData,
205-
block: {
206-
$0.addRetireConnectionID(FrameRetireConnectionID(sequence: sequence))
207-
}
208-
)
209-
}
205+
retireOutboundCID(forPathGoingAway: path)
210206
path.changeState(to: .routeUnavailable)
211207
break
212208
}
@@ -225,5 +221,35 @@ extension QUICConnection {
225221
sendFrames(on: path)
226222
}
227223
}
224+
225+
// Retires a path's outbound CID and queues a RETIRE_CONNECTION_ID frame for it.
226+
func retireOutboundCID(forPathGoingAway path: QUICPath) {
227+
guard path.isOpenForSending, !path.hasPreAssignedCIDs, let dcid = path.dcid,
228+
let sequence = remoteCIDs.retire(connectionID: dcid)
229+
else {
230+
return
231+
}
232+
withPendingItems(for: .applicationData) {
233+
$0.addRetireConnectionID(FrameRetireConnectionID(sequence: sequence))
234+
}
235+
}
236+
237+
// Removes a path we migrated away from.
238+
func tearDownMigratedPath(_ oldPath: QUICPath) {
239+
guard oldPath !== currentPath else {
240+
log.fault("Refusing to tear down the current path \(oldPath.identifier)")
241+
return
242+
}
243+
log.notice("Tearing down old path \(oldPath.identifier) after migration")
244+
245+
retireOutboundCID(forPathGoingAway: oldPath)
246+
247+
if oldPath.state.isValidStateChange(to: .routeUnavailable) {
248+
oldPath.changeState(to: .routeUnavailable)
249+
}
250+
oldPath.tearDownLowerStack()
251+
multiplexingPaths.removeValue(forKey: oldPath.identifier)
252+
sendFrames()
253+
}
228254
}
229255
#endif

Sources/SwiftNetwork/QUIC/QUICPath.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,10 @@ public final class QUICPath: MultiplexingDatagramPath<QUICConnection>, Equatable
623623
parentProtocol.migration.migrate(to: self, connection: parentProtocol)
624624
}
625625
}
626+
627+
func tearDownLowerStack() {
628+
try? lower.invokeDetach(self.reference)
629+
}
626630
}
627631

628632
// Congestion Control access

0 commit comments

Comments
 (0)