Skip to content

Commit cd80fe4

Browse files
committed
Ensure that the Churn candidates' MID matches the SDP.
Fixes UWNetworksLab/uProxy-p2p#2143
1 parent a45253d commit cd80fe4

File tree

1 file changed

+42
-7
lines changed

1 file changed

+42
-7
lines changed

src/churn/churn.ts

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ export var filterCandidatesFromSdp = (sdp:string) : string => {
3131
}).join('\n');
3232
}
3333

34+
export var getMidFromSdp = (sdp:string) : string => {
35+
var mids :string[] = [];
36+
sdp.split('\n').forEach((s) => {
37+
var match = s.match(/^a=mid:(\S+)\s*$/);
38+
if (match) {
39+
mids.push(match[1]);
40+
}
41+
});
42+
if (mids.length !== 1) {
43+
throw new Error('Expected 1 mid, but there are actually ' + mids.length);
44+
}
45+
return mids[0];
46+
}
47+
3448
export interface NatPair {
3549
internal: net.Endpoint;
3650
external: net.Endpoint;
@@ -137,13 +151,17 @@ export class Connection implements peerconnection.PeerConnection<ChurnSignalling
137151
// Number of instances created, for logging purposes.
138152
private static id_ = 0;
139153

154+
// The "mid"
155+
private mid_ :string;
156+
140157
// Maximum time to spend gathering ICE candidates.
141158
// We cap this so that slow STUN servers, in the absence
142159
// of trickle ICE, don't make the user wait unnecessarily.
143160
private static PROBE_TIMEOUT_MS_ = 3000;
144161

145162
public peerOpenedChannelQueue :handler.QueueHandler<peerconnection.DataChannel, void>;
146163
public signalForPeerQueue :handler.Queue<ChurnSignallingMessage, void>;
164+
private candidateQueue_ :handler.Queue<Candidate, void>;
147165

148166
public onceConnected :Promise<void>;
149167
public onceClosed :Promise<void>;
@@ -196,6 +214,7 @@ export class Connection implements peerconnection.PeerConnection<ChurnSignalling
196214
Connection.id_++;
197215

198216
this.signalForPeerQueue = new handler.Queue<ChurnSignallingMessage,void>();
217+
this.candidateQueue_ = new handler.Queue<Candidate,void>();
199218

200219
this.configureObfuscatedConnection_();
201220
// When the probe connection is complete, it will trigger the
@@ -246,13 +265,10 @@ export class Connection implements peerconnection.PeerConnection<ChurnSignalling
246265
}
247266
}
248267

249-
// It's immediately safe to send each candidate to the remote peer,
250-
// because the remote peer will retry for several seconds, and the
251-
// probe connection will not respond to any pings because it doesn't
252-
// have a remote description.
253-
this.signalForPeerQueue.handle({
254-
webrtcMessage: message
255-
});
268+
// We enqueue this candidate for transmission to the remote peer.
269+
// This queue will start draining once an Offer is available, so
270+
// that we can make sure that the mid matches.
271+
this.candidateQueue_.handle(c);
256272

257273
// We cannot rebind any local ports until the probe connection has
258274
// released them, so we have to store them and wait until probing is
@@ -281,6 +297,20 @@ export class Connection implements peerconnection.PeerConnection<ChurnSignalling
281297
this.probeConnection_.negotiateConnection();
282298
}
283299

300+
private candidateQueueHandler_ = (candidate:Candidate) : Promise<void> => {
301+
// The candidate was generated by the probe connection, which might have a
302+
// different mid from the obfuscated connection. Make sure that the mid
303+
// matches before we transmit the candidate.
304+
candidate.sdpMid = this.mid_;
305+
306+
return this.signalForPeerQueue.handle({
307+
webrtcMessage: {
308+
type: signals.Type.CANDIDATE,
309+
candidate: candidate.toRTCIceCandidate()
310+
}
311+
});
312+
}
313+
284314
private processProbeCandidates_ = (candidates:Candidate[]) => {
285315
candidates.forEach((c) => {
286316
this.pipe_.bindLocal(c.getLocalEndpoint());
@@ -367,6 +397,11 @@ export class Connection implements peerconnection.PeerConnection<ChurnSignalling
367397
webrtcMessage: message
368398
};
369399
this.signalForPeerQueue.handle(churnSignal);
400+
401+
// We need to know the MID so that we can rewrite candidates to
402+
// have the correct MID before transmitting them.
403+
this.mid_ = getMidFromSdp(message.description.sdp);
404+
this.candidateQueue_.setHandler(this.candidateQueueHandler_);
370405
} else if (message.type === signals.Type.CANDIDATE) {
371406
// This will tell us on which port webrtc is operating.
372407
// There's no need to send this to the peer because it can

0 commit comments

Comments
 (0)