Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
shinyoshiaki committed Jan 2, 2025
1 parent 8f9025c commit 39ecdb6
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 120 deletions.
92 changes: 61 additions & 31 deletions packages/ice/src/ice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class Connection implements IceConnection {
options: IceOptions;
remoteCandidatesEnd = false;
localCandidatesEnd = false;
generation = -1;
generation = 0;
private readonly tieBreaker: bigint = BigInt(
new Uint64BE(randomBytes(64)).toString(),
);
Expand All @@ -75,7 +75,7 @@ export class Connection implements IceConnection {
readonly onIceCandidate: Event<[Candidate]> = new Event();

constructor(
public iceControlling: boolean,
private _iceControlling: boolean,
options?: Partial<IceOptions>,
) {
this.options = {
Expand All @@ -88,20 +88,33 @@ export class Connection implements IceConnection {
19302,
];
this.turnServer = validateAddress(turnServer);
this.restart();
}

restart() {
get iceControlling() {
return this._iceControlling;
}

set iceControlling(value: boolean) {
if (this.generation > 0 || this.nominated) {
return;
}
this._iceControlling = value;
for (const pair of this.checkList) {
pair.iceControlling = value;
}
}

async restart() {
this.localUserName = randomString(4);
this.localPassword = randomString(22);
this.remoteIsLite = false;
this.remoteUsername = "";
this.remotePassword = "";
this.checkList = [];
this.localCandidates = [];
this.remoteCandidatesEnd = false;
this.localCandidatesEnd = false;
this.state = "new";
this.lookup?.close?.();
this.lookup = undefined;
this._remoteCandidates = [];
this.nominated = undefined;
Expand All @@ -111,13 +124,23 @@ export class Connection implements IceConnection {
this.earlyChecks = [];
this.earlyChecksDone = false;
this.localCandidatesStart = false;
for (const protocol of this.protocols) {
await protocol.close();
}
this.protocols = [];
this.queryConsentHandle?.resolve?.();
this.queryConsentHandle = undefined;
this.promiseGatherCandidates = undefined;

this.generation++;
}

resetNominatedPair() {
log("resetNominatedPair");
this.nominated = undefined;
this.nominating = false;
}

setRemoteParams({
iceLite,
usernameFragment,
Expand Down Expand Up @@ -438,7 +461,9 @@ export class Connection implements IceConnection {
this.unfreezeInitial();

// # handle early checks
this.earlyChecks.forEach((earlyCheck) => this.checkIncoming(...earlyCheck));
for (const earlyCheck of this.earlyChecks) {
this.checkIncoming(...earlyCheck);
}
this.earlyChecks = [];
this.earlyChecksDone = true;

Expand Down Expand Up @@ -474,7 +499,7 @@ export class Connection implements IceConnection {
const [firstPair] = this.checkList;
if (!firstPair) return;
if (firstPair.state === CandidatePairState.FROZEN) {
this.setPairState(firstPair, CandidatePairState.WAITING);
firstPair.updateState(CandidatePairState.WAITING);
}

// # unfreeze pairs with same component but different foundations
Expand All @@ -485,7 +510,7 @@ export class Connection implements IceConnection {
!seenFoundations.has(pair.localCandidate.foundation) &&
pair.state === CandidatePairState.FROZEN
) {
this.setPairState(pair, CandidatePairState.WAITING);
pair.updateState(CandidatePairState.WAITING);
seenFoundations.add(pair.localCandidate.foundation);
}
}
Expand Down Expand Up @@ -642,7 +667,9 @@ export class Connection implements IceConnection {

if (remoteCandidate.host.includes(".local")) {
try {
if (this.state === "closed") return;
if (this.state === "closed") {
return;
}
if (!this.lookup) {
this.lookup = new MdnsLookup();
}
Expand Down Expand Up @@ -677,9 +704,9 @@ export class Connection implements IceConnection {
};

getDefaultCandidate() {
const candidates = this.localCandidates.sort(
(a, b) => a.priority - b.priority,
);
const candidates = this.localCandidates
.sort((a, b) => a.priority - b.priority)
.reverse();
const [candidate] = candidates;
return candidate;
}
Expand Down Expand Up @@ -717,11 +744,6 @@ export class Connection implements IceConnection {
return pair;
}

private setPairState(pair: CandidatePair, state: CandidatePairState) {
log("setPairState", pair.toJSON(), CandidatePairState[state]);
pair.updateState(state);
}

private switchRole(iceControlling: boolean) {
log("switch role", iceControlling);
this.iceControlling = iceControlling;
Expand Down Expand Up @@ -754,7 +776,7 @@ export class Connection implements IceConnection {
p.state,
)
) {
this.setPairState(p, CandidatePairState.FAILED);
p.updateState(CandidatePairState.FAILED);
}
}
}
Expand All @@ -777,7 +799,7 @@ export class Connection implements IceConnection {
p.localCandidate.foundation === pair.localCandidate.foundation &&
p.state === CandidatePairState.FROZEN
) {
this.setPairState(p, CandidatePairState.WAITING);
p.updateState(CandidatePairState.WAITING);
}
}
}
Expand Down Expand Up @@ -815,7 +837,7 @@ export class Connection implements IceConnection {

log("check start", pair.toJSON());

this.setPairState(pair, CandidatePairState.IN_PROGRESS);
pair.updateState(CandidatePairState.IN_PROGRESS);

const nominate = this.iceControlling && !this.remoteIsLite;
const request = this.buildRequest(nominate);
Expand Down Expand Up @@ -847,7 +869,7 @@ export class Connection implements IceConnection {
} else {
// timeout
log("CandidatePairState.FAILED", pair.toJSON());
this.setPairState(pair, CandidatePairState.FAILED);
pair.updateState(CandidatePairState.FAILED);
this.checkComplete(pair);
r();
return;
Expand All @@ -856,7 +878,7 @@ export class Connection implements IceConnection {

// # check remote address matches
if (!isEqual(result.addr, pair.remoteAddr)) {
this.setPairState(pair, CandidatePairState.FAILED);
pair.updateState(CandidatePairState.FAILED);
this.checkComplete(pair);
r();
return;
Expand All @@ -877,18 +899,23 @@ export class Connection implements IceConnection {
Buffer.from(this.remotePassword, "utf8"),
);
} catch (error) {
this.setPairState(pair, CandidatePairState.FAILED);
pair.updateState(CandidatePairState.FAILED);
this.checkComplete(pair);
return;
}
pair.nominated = true;
}

this.setPairState(pair, CandidatePairState.SUCCEEDED);
pair.updateState(CandidatePairState.SUCCEEDED);
this.checkComplete(pair);
r();
});

private addPair(pair: CandidatePair) {
this.checkList.push(pair);
this.sortCheckList();
}

// 7.2. STUN Server Procedures
// 7.2.1.3、7.2.1.4、および7.2.1.5
checkIncoming(message: Message, addr: Address, protocol: Protocol) {
Expand Down Expand Up @@ -928,10 +955,9 @@ export class Connection implements IceConnection {
// find pair
let pair = this.findPair(protocol, remoteCandidate);
if (!pair) {
pair = new CandidatePair(protocol, remoteCandidate);
this.setPairState(pair, CandidatePairState.WAITING);
this.checkList.push(pair);
this.sortCheckList();
pair = new CandidatePair(protocol, remoteCandidate, this.iceControlling);
pair.updateState(CandidatePairState.WAITING);
this.addPair(pair);
}

// 7.2.1.4. Triggered Checks
Expand Down Expand Up @@ -963,15 +989,19 @@ export class Connection implements IceConnection {
protocol.localCandidate?.canPairWith(remoteCandidate) &&
!this.findPair(protocol, remoteCandidate)
) {
const pair = new CandidatePair(protocol, remoteCandidate);
const pair = new CandidatePair(
protocol,
remoteCandidate,
this.iceControlling,
);
if (
this.options.filterCandidatePair &&
!this.options.filterCandidatePair(pair)
) {
return;
}
this.checkList.push(pair);
this.setPairState(pair, CandidatePairState.WAITING);
pair.updateState(CandidatePairState.WAITING);
this.addPair(pair);
}
}

Expand Down
15 changes: 13 additions & 2 deletions packages/ice/src/iceBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@ export interface IceConnection {
localCandidates: Candidate[];
stunServer?: Address;
turnServer?: Address;
generation: number;
options: IceOptions;
remoteCandidatesEnd: boolean;
localCandidatesEnd: boolean;
state: IceState;
lookup?: MdnsLookup;
nominated?:CandidatePair
nominated?: CandidatePair;

readonly onData: Event<[Buffer]>;
readonly stateChanged: Event<[IceState]>;
readonly onIceCandidate: Event<[Candidate]>;

restart(): void;
restart(): Promise<void>;

setRemoteParams(params: {
iceLite: boolean;
Expand All @@ -53,6 +54,7 @@ export interface IceConnection {
send(data: Buffer): Promise<void>;

getDefaultCandidate(): Candidate | undefined;
resetNominatedPair(): void;
}

export class CandidatePair {
Expand All @@ -75,6 +77,7 @@ export class CandidatePair {
constructor(
public protocol: Protocol,
public remoteCandidate: Candidate,
public iceControlling: boolean,
) {}

updateState(state: CandidatePairState) {
Expand All @@ -95,6 +98,14 @@ export class CandidatePair {
get component() {
return this.localCandidate.component;
}

get priority() {
return candidatePairPriority(
this.localCandidate,
this.remoteCandidate,
this.iceControlling,
);
}
}

export const ICE_COMPLETED = 1 as const;
Expand Down
4 changes: 4 additions & 0 deletions packages/ice/src/stun/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ export class Message extends AttributeRepository {
}

toJSON() {
return this.json;
}

get json() {
return {
messageMethod: methods[this.messageMethod],
messageClass: classes[this.messageClass],
Expand Down
20 changes: 9 additions & 11 deletions packages/ice/src/stun/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { classes } from "./const";
import { type Message, parseMessage } from "./message";
import { Transaction } from "./transaction";

const log = debug("packages/ice/src/stun/protocol.ts");
const log = debug("werift-ice : packages/ice/src/stun/protocol.ts");

export class StunProtocol implements Protocol {
static readonly type = "stun";
Expand All @@ -22,18 +22,12 @@ export class StunProtocol implements Protocol {
localCandidate?: Candidate;
sentMessage?: Message;
localAddress?: string;
onRequestReceived = new Event<[Message, Address, Buffer]>();
onDataReceived = new Event<[Buffer]>();

private readonly closed = new Event();
readonly onRequestReceived = new Event<[Message, Address, Buffer]>();
readonly onDataReceived = new Event<[Buffer]>();

constructor() {}

connectionLost() {
this.closed.execute();
this.closed.complete();
}

connectionMade = async (
useIpv4: boolean,
portRange?: [number, number],
Expand All @@ -53,7 +47,9 @@ export class StunProtocol implements Protocol {
);
}

this.transport.onData = (data, addr) => this.datagramReceived(data, addr);
this.transport.onData = (data, addr) => {
this.datagramReceived(data, addr);
};
};

private datagramReceived(data: Buffer, addr: Address) {
Expand All @@ -65,7 +61,7 @@ export class StunProtocol implements Protocol {
}
return;
}
// log("parseMessage", addr, message);
log("parseMessage", addr, message.toJSON());
if (
(message.messageClass === classes.RESPONSE ||
message.messageClass === classes.ERROR) &&
Expand Down Expand Up @@ -136,5 +132,7 @@ export class StunProtocol implements Protocol {
transaction.cancel();
});
await this.transport.close();
this.onRequestReceived.complete();
this.onDataReceived.complete();
}
}
Loading

0 comments on commit 39ecdb6

Please sign in to comment.