@blockcast/mmt-transport 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abr-controller.d.ts +94 -0
- package/dist/abr-controller.d.ts.map +1 -0
- package/dist/abr-controller.js +174 -0
- package/dist/abr-controller.js.map +1 -0
- package/dist/amt-gateway.d.ts +160 -0
- package/dist/amt-gateway.d.ts.map +1 -0
- package/dist/amt-gateway.js +390 -0
- package/dist/amt-gateway.js.map +1 -0
- package/dist/clock.d.ts +104 -0
- package/dist/clock.d.ts.map +1 -0
- package/dist/clock.js +183 -0
- package/dist/clock.js.map +1 -0
- package/dist/driad-discovery.d.ts +50 -0
- package/dist/driad-discovery.d.ts.map +1 -0
- package/dist/driad-discovery.js +170 -0
- package/dist/driad-discovery.js.map +1 -0
- package/dist/fec-client.d.ts +442 -0
- package/dist/fec-client.d.ts.map +1 -0
- package/dist/fec-client.js +784 -0
- package/dist/fec-client.js.map +1 -0
- package/dist/fec-client.test.d.ts +8 -0
- package/dist/fec-client.test.d.ts.map +1 -0
- package/dist/fec-client.test.js +112 -0
- package/dist/fec-client.test.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/transport-manager.d.ts +114 -0
- package/dist/transport-manager.d.ts.map +1 -0
- package/dist/transport-manager.js +396 -0
- package/dist/transport-manager.js.map +1 -0
- package/dist/types.d.ts +356 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +85 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
- package/src/abr-controller.ts +227 -0
- package/src/amt-gateway.ts +511 -0
- package/src/clock.ts +212 -0
- package/src/driad-discovery.ts +193 -0
- package/src/fec-client.test.ts +140 -0
- package/src/fec-client.ts +1097 -0
- package/src/index.ts +122 -0
- package/src/transport-manager.ts +460 -0
- package/src/types.ts +420 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @blockcast/transport - Adaptive Bitrate Controller
|
|
3
|
+
*
|
|
4
|
+
* Progressive adaptive bitrate increase based on network conditions.
|
|
5
|
+
* Monitors received bandwidth and packet loss to adjust quality levels.
|
|
6
|
+
*
|
|
7
|
+
* Per draft-ramadan-moq-fec-00, ABR decisions should use the **effective loss rate**
|
|
8
|
+
* after FEC recovery, not the raw transport-level loss rate. This allows FEC to
|
|
9
|
+
* mask burst losses without unnecessarily downgrading quality.
|
|
10
|
+
*/
|
|
11
|
+
import type { QualityLevel } from "./types.js";
|
|
12
|
+
/**
|
|
13
|
+
* FEC statistics for ABR decisions
|
|
14
|
+
*/
|
|
15
|
+
export interface FecStatsForAbr {
|
|
16
|
+
/** Raw loss rate before FEC recovery (0.0-1.0) */
|
|
17
|
+
rawLossRate: number;
|
|
18
|
+
/** Effective loss rate after FEC recovery (0.0-1.0) */
|
|
19
|
+
effectiveLossRate: number;
|
|
20
|
+
/** FEC recovery rate (percentage of lost packets recovered) */
|
|
21
|
+
recoveryRate: number;
|
|
22
|
+
/** Whether FEC is enabled */
|
|
23
|
+
fecEnabled: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Standard quality levels for progressive ABR
|
|
27
|
+
*/
|
|
28
|
+
export declare const QUALITY_LEVELS: QualityLevel[];
|
|
29
|
+
/**
|
|
30
|
+
* Progressive Adaptive Bitrate Controller
|
|
31
|
+
*
|
|
32
|
+
* Features:
|
|
33
|
+
* - Monitors bandwidth via received bytes over time window
|
|
34
|
+
* - Tracks packet loss rate (raw and effective after FEC)
|
|
35
|
+
* - Uses effective loss rate for ABR decisions per draft-ramadan-moq-fec-00
|
|
36
|
+
* - Progressive quality upgrades (waits for stability)
|
|
37
|
+
* - Fast quality downgrades on congestion
|
|
38
|
+
*/
|
|
39
|
+
export declare class AdaptiveBitrateController {
|
|
40
|
+
private currentQualityIndex;
|
|
41
|
+
private history;
|
|
42
|
+
private readonly historyWindow;
|
|
43
|
+
private readonly upgradeThreshold;
|
|
44
|
+
private readonly downgradeThreshold;
|
|
45
|
+
private readonly stabilityPeriod;
|
|
46
|
+
private lastQualityChange;
|
|
47
|
+
private onQualityChange?;
|
|
48
|
+
private fecStats;
|
|
49
|
+
constructor(initialQuality?: QualityLevel);
|
|
50
|
+
setCallback(callback: (quality: QualityLevel) => void): void;
|
|
51
|
+
getCurrentQuality(): QualityLevel;
|
|
52
|
+
/**
|
|
53
|
+
* Record network sample for bitrate adaptation
|
|
54
|
+
*
|
|
55
|
+
* @param bytesReceived - Bytes received in this sample
|
|
56
|
+
* @param packetsLost - Packets lost (raw, before FEC recovery)
|
|
57
|
+
*/
|
|
58
|
+
recordSample(bytesReceived: number, packetsLost: number): void;
|
|
59
|
+
/**
|
|
60
|
+
* Update FEC statistics for ABR decisions
|
|
61
|
+
*
|
|
62
|
+
* Per draft-ramadan-moq-fec-00, ABR should use the effective loss rate
|
|
63
|
+
* (after FEC recovery) rather than raw transport loss rate.
|
|
64
|
+
*
|
|
65
|
+
* @param stats - FEC statistics from the FEC decoder
|
|
66
|
+
*/
|
|
67
|
+
setFecStats(stats: FecStatsForAbr): void;
|
|
68
|
+
/**
|
|
69
|
+
* Get current FEC statistics
|
|
70
|
+
*/
|
|
71
|
+
getFecStats(): FecStatsForAbr;
|
|
72
|
+
private calculateMetrics;
|
|
73
|
+
private upgrade;
|
|
74
|
+
private downgrade;
|
|
75
|
+
/**
|
|
76
|
+
* Force quality level (for testing)
|
|
77
|
+
*/
|
|
78
|
+
setQuality(name: string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Get current metrics including both raw and effective loss rates
|
|
81
|
+
*/
|
|
82
|
+
getMetrics(): {
|
|
83
|
+
measuredBitrate: number;
|
|
84
|
+
rawLossRate: number;
|
|
85
|
+
effectiveLossRate: number;
|
|
86
|
+
fecEnabled: boolean;
|
|
87
|
+
sampleCount: number;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Reset history and start fresh
|
|
91
|
+
*/
|
|
92
|
+
reset(): void;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=abr-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abr-controller.d.ts","sourceRoot":"","sources":["../src/abr-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,UAAU,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,YAAY,EAQxC,CAAC;AAEF;;;;;;;;;GASG;AACH,qBAAa,yBAAyB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,OAAO,CAA2E;IAC1F,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAO;IACxC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IAC1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAEzC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,eAAe,CAAC,CAAkC;IAG1D,OAAO,CAAC,QAAQ,CAKd;gBAEU,cAAc,CAAC,EAAE,YAAY;IAMzC,WAAW,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI;IAIrD,iBAAiB,IAAI,YAAY;IAIjC;;;;;OAKG;IACH,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAwCvD;;;;;;;OAOG;IACH,WAAW,CAAC,KAAK,EAAE,cAAc;IAIjC;;OAEG;IACH,WAAW,IAAI,cAAc;IAI7B,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,SAAS;IAYjB;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM;IASvB;;OAEG;IACH,UAAU,IAAI;QACb,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,UAAU,EAAE,OAAO,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACpB;IAWD;;OAEG;IACH,KAAK;CAIL"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @blockcast/transport - Adaptive Bitrate Controller
|
|
3
|
+
*
|
|
4
|
+
* Progressive adaptive bitrate increase based on network conditions.
|
|
5
|
+
* Monitors received bandwidth and packet loss to adjust quality levels.
|
|
6
|
+
*
|
|
7
|
+
* Per draft-ramadan-moq-fec-00, ABR decisions should use the **effective loss rate**
|
|
8
|
+
* after FEC recovery, not the raw transport-level loss rate. This allows FEC to
|
|
9
|
+
* mask burst losses without unnecessarily downgrading quality.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Standard quality levels for progressive ABR
|
|
13
|
+
*/
|
|
14
|
+
export const QUALITY_LEVELS = [
|
|
15
|
+
{ name: "240p", bitrate: 300_000, width: 426, height: 240, fps: 15 },
|
|
16
|
+
{ name: "360p", bitrate: 500_000, width: 640, height: 360, fps: 24 },
|
|
17
|
+
{ name: "480p", bitrate: 1_000_000, width: 854, height: 480, fps: 30 },
|
|
18
|
+
{ name: "720p", bitrate: 2_500_000, width: 1280, height: 720, fps: 30 },
|
|
19
|
+
{ name: "1080p", bitrate: 5_000_000, width: 1920, height: 1080, fps: 30 },
|
|
20
|
+
{ name: "1440p", bitrate: 8_000_000, width: 2560, height: 1440, fps: 30 },
|
|
21
|
+
{ name: "4K", bitrate: 15_000_000, width: 3840, height: 2160, fps: 30 },
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Progressive Adaptive Bitrate Controller
|
|
25
|
+
*
|
|
26
|
+
* Features:
|
|
27
|
+
* - Monitors bandwidth via received bytes over time window
|
|
28
|
+
* - Tracks packet loss rate (raw and effective after FEC)
|
|
29
|
+
* - Uses effective loss rate for ABR decisions per draft-ramadan-moq-fec-00
|
|
30
|
+
* - Progressive quality upgrades (waits for stability)
|
|
31
|
+
* - Fast quality downgrades on congestion
|
|
32
|
+
*/
|
|
33
|
+
export class AdaptiveBitrateController {
|
|
34
|
+
currentQualityIndex;
|
|
35
|
+
history = [];
|
|
36
|
+
historyWindow = 10_000; // 10 second window
|
|
37
|
+
upgradeThreshold = 0.8; // 80% of target bitrate sustained
|
|
38
|
+
downgradeThreshold = 0.5; // 50% of target bitrate triggers downgrade
|
|
39
|
+
stabilityPeriod = 5_000; // Wait 5s before upgrading
|
|
40
|
+
lastQualityChange = 0;
|
|
41
|
+
onQualityChange;
|
|
42
|
+
// FEC stats for effective loss rate calculation
|
|
43
|
+
fecStats = {
|
|
44
|
+
rawLossRate: 0,
|
|
45
|
+
effectiveLossRate: 0,
|
|
46
|
+
recoveryRate: 1,
|
|
47
|
+
fecEnabled: false,
|
|
48
|
+
};
|
|
49
|
+
constructor(initialQuality) {
|
|
50
|
+
this.currentQualityIndex = initialQuality ? QUALITY_LEVELS.findIndex((q) => q.name === initialQuality.name) : 0;
|
|
51
|
+
if (this.currentQualityIndex < 0)
|
|
52
|
+
this.currentQualityIndex = 0;
|
|
53
|
+
}
|
|
54
|
+
setCallback(callback) {
|
|
55
|
+
this.onQualityChange = callback;
|
|
56
|
+
}
|
|
57
|
+
getCurrentQuality() {
|
|
58
|
+
return QUALITY_LEVELS[this.currentQualityIndex];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Record network sample for bitrate adaptation
|
|
62
|
+
*
|
|
63
|
+
* @param bytesReceived - Bytes received in this sample
|
|
64
|
+
* @param packetsLost - Packets lost (raw, before FEC recovery)
|
|
65
|
+
*/
|
|
66
|
+
recordSample(bytesReceived, packetsLost) {
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
this.history.push({ timestamp: now, bytesReceived, packetsLost });
|
|
69
|
+
// Prune old samples
|
|
70
|
+
this.history = this.history.filter((s) => now - s.timestamp < this.historyWindow);
|
|
71
|
+
// Calculate metrics
|
|
72
|
+
const { measuredBitrate, lossRate: rawLossRate } = this.calculateMetrics();
|
|
73
|
+
const currentQuality = this.getCurrentQuality();
|
|
74
|
+
// Per draft-ramadan-moq-fec-00: Use effective loss rate after FEC for ABR decisions
|
|
75
|
+
// This allows FEC to mask burst losses without triggering unnecessary downgrades
|
|
76
|
+
const effectiveLossRate = this.fecStats.fecEnabled
|
|
77
|
+
? this.fecStats.effectiveLossRate
|
|
78
|
+
: rawLossRate;
|
|
79
|
+
// Decision logic
|
|
80
|
+
if (now - this.lastQualityChange < this.stabilityPeriod) {
|
|
81
|
+
return; // Wait for stability
|
|
82
|
+
}
|
|
83
|
+
// Check for downgrade - use effective loss rate (post-FEC)
|
|
84
|
+
// Only downgrade if FEC cannot recover the losses
|
|
85
|
+
if (effectiveLossRate > 0.05 || measuredBitrate < currentQuality.bitrate * this.downgradeThreshold) {
|
|
86
|
+
this.downgrade();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Check for upgrade (progressive increase) - use effective loss rate
|
|
90
|
+
if (measuredBitrate > currentQuality.bitrate * this.upgradeThreshold &&
|
|
91
|
+
effectiveLossRate < 0.01 &&
|
|
92
|
+
this.currentQualityIndex < QUALITY_LEVELS.length - 1) {
|
|
93
|
+
this.upgrade();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Update FEC statistics for ABR decisions
|
|
98
|
+
*
|
|
99
|
+
* Per draft-ramadan-moq-fec-00, ABR should use the effective loss rate
|
|
100
|
+
* (after FEC recovery) rather than raw transport loss rate.
|
|
101
|
+
*
|
|
102
|
+
* @param stats - FEC statistics from the FEC decoder
|
|
103
|
+
*/
|
|
104
|
+
setFecStats(stats) {
|
|
105
|
+
this.fecStats = stats;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get current FEC statistics
|
|
109
|
+
*/
|
|
110
|
+
getFecStats() {
|
|
111
|
+
return { ...this.fecStats };
|
|
112
|
+
}
|
|
113
|
+
calculateMetrics() {
|
|
114
|
+
if (this.history.length < 2) {
|
|
115
|
+
return { measuredBitrate: 0, lossRate: 0 };
|
|
116
|
+
}
|
|
117
|
+
const totalBytes = this.history.reduce((sum, s) => sum + s.bytesReceived, 0);
|
|
118
|
+
const totalLost = this.history.reduce((sum, s) => sum + s.packetsLost, 0);
|
|
119
|
+
const duration = (this.history[this.history.length - 1].timestamp - this.history[0].timestamp) / 1000;
|
|
120
|
+
const measuredBitrate = duration > 0 ? (totalBytes * 8) / duration : 0;
|
|
121
|
+
const lossRate = totalLost / (this.history.length + totalLost);
|
|
122
|
+
return { measuredBitrate, lossRate };
|
|
123
|
+
}
|
|
124
|
+
upgrade() {
|
|
125
|
+
if (this.currentQualityIndex >= QUALITY_LEVELS.length - 1)
|
|
126
|
+
return;
|
|
127
|
+
this.currentQualityIndex++;
|
|
128
|
+
this.lastQualityChange = Date.now();
|
|
129
|
+
const newQuality = this.getCurrentQuality();
|
|
130
|
+
console.log(`[ABR] Upgrading to ${newQuality.name} (${newQuality.bitrate / 1_000_000}Mbps)`);
|
|
131
|
+
this.onQualityChange?.(newQuality);
|
|
132
|
+
}
|
|
133
|
+
downgrade() {
|
|
134
|
+
if (this.currentQualityIndex <= 0)
|
|
135
|
+
return;
|
|
136
|
+
this.currentQualityIndex--;
|
|
137
|
+
this.lastQualityChange = Date.now();
|
|
138
|
+
const newQuality = this.getCurrentQuality();
|
|
139
|
+
console.log(`[ABR] Downgrading to ${newQuality.name} (${newQuality.bitrate / 1_000_000}Mbps)`);
|
|
140
|
+
this.onQualityChange?.(newQuality);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Force quality level (for testing)
|
|
144
|
+
*/
|
|
145
|
+
setQuality(name) {
|
|
146
|
+
const index = QUALITY_LEVELS.findIndex((q) => q.name === name);
|
|
147
|
+
if (index >= 0) {
|
|
148
|
+
this.currentQualityIndex = index;
|
|
149
|
+
this.lastQualityChange = Date.now();
|
|
150
|
+
this.onQualityChange?.(this.getCurrentQuality());
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get current metrics including both raw and effective loss rates
|
|
155
|
+
*/
|
|
156
|
+
getMetrics() {
|
|
157
|
+
const { measuredBitrate, lossRate: rawLossRate } = this.calculateMetrics();
|
|
158
|
+
return {
|
|
159
|
+
measuredBitrate,
|
|
160
|
+
rawLossRate,
|
|
161
|
+
effectiveLossRate: this.fecStats.fecEnabled ? this.fecStats.effectiveLossRate : rawLossRate,
|
|
162
|
+
fecEnabled: this.fecStats.fecEnabled,
|
|
163
|
+
sampleCount: this.history.length,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Reset history and start fresh
|
|
168
|
+
*/
|
|
169
|
+
reset() {
|
|
170
|
+
this.history = [];
|
|
171
|
+
this.lastQualityChange = 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=abr-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abr-controller.js","sourceRoot":"","sources":["../src/abr-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @blockcast/transport - AMT Gateway
|
|
3
|
+
*
|
|
4
|
+
* Consolidated AMT (Automatic Multicast Tunneling) implementation
|
|
5
|
+
* supporting both Service Worker and Direct Sockets approaches.
|
|
6
|
+
*
|
|
7
|
+
* RFC 7450: Automatic Multicast Tunneling
|
|
8
|
+
*/
|
|
9
|
+
import type { GroupKey, PacketMetadata } from "./types.js";
|
|
10
|
+
/** AMT gateway states */
|
|
11
|
+
declare const GATEWAY_STATES: {
|
|
12
|
+
readonly IDLE: "idle";
|
|
13
|
+
readonly DISCOVERING: "discovering";
|
|
14
|
+
readonly REQUESTING: "requesting";
|
|
15
|
+
readonly QUERYING: "querying";
|
|
16
|
+
readonly ACTIVE: "active";
|
|
17
|
+
readonly LEAVING: "leaving";
|
|
18
|
+
readonly CLOSED: "closed";
|
|
19
|
+
};
|
|
20
|
+
type GatewayState = (typeof GATEWAY_STATES)[keyof typeof GATEWAY_STATES];
|
|
21
|
+
/** AMT subscription configuration */
|
|
22
|
+
export interface AMTSubscriptionConfig {
|
|
23
|
+
key: GroupKey;
|
|
24
|
+
relayAddress?: string;
|
|
25
|
+
relayPort?: number;
|
|
26
|
+
onPacket: (data: ArrayBuffer, metadata: PacketMetadata) => void;
|
|
27
|
+
onError: (error: Error) => void;
|
|
28
|
+
}
|
|
29
|
+
/** AMT packet info */
|
|
30
|
+
export interface AMTPacketInfo {
|
|
31
|
+
data: Uint8Array;
|
|
32
|
+
srcAddress: string;
|
|
33
|
+
dstAddress: string;
|
|
34
|
+
srcPort: number;
|
|
35
|
+
dstPort: number;
|
|
36
|
+
groupKey: string;
|
|
37
|
+
timestamp: number;
|
|
38
|
+
}
|
|
39
|
+
/** AMT Gateway options */
|
|
40
|
+
export interface AMTGatewayOptions {
|
|
41
|
+
relayAddress: string;
|
|
42
|
+
relayPort?: number;
|
|
43
|
+
onPacket?: (packet: AMTPacketInfo) => void;
|
|
44
|
+
onStateChange?: (newState: GatewayState, oldState: GatewayState) => void;
|
|
45
|
+
onError?: (error: Error) => void;
|
|
46
|
+
onLog?: (message: string) => void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* AMT Gateway Manager (Service Worker based)
|
|
50
|
+
*
|
|
51
|
+
* Manages AMT tunnel subscriptions using Service Worker for UDP communication.
|
|
52
|
+
* Handles DRIAD discovery, AMT handshake, and packet decapsulation.
|
|
53
|
+
*/
|
|
54
|
+
export declare class AMTGatewayManager {
|
|
55
|
+
private subscriptions;
|
|
56
|
+
private messageHandler?;
|
|
57
|
+
private pendingPackets;
|
|
58
|
+
private driad;
|
|
59
|
+
constructor();
|
|
60
|
+
/**
|
|
61
|
+
* Subscribe via AMT tunnel
|
|
62
|
+
*/
|
|
63
|
+
subscribe(config: AMTSubscriptionConfig): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* Unsubscribe from AMT tunnel
|
|
66
|
+
*/
|
|
67
|
+
unsubscribe(handle: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Get list of active subscriptions
|
|
70
|
+
*/
|
|
71
|
+
getSubscriptions(): string[];
|
|
72
|
+
/**
|
|
73
|
+
* Handle packet from service worker
|
|
74
|
+
*/
|
|
75
|
+
private handlePacket;
|
|
76
|
+
/**
|
|
77
|
+
* Handle socket error from service worker
|
|
78
|
+
*/
|
|
79
|
+
private handleSocketError;
|
|
80
|
+
/**
|
|
81
|
+
* Cleanup on destroy
|
|
82
|
+
*/
|
|
83
|
+
destroy(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Get key string for HashMap
|
|
86
|
+
*/
|
|
87
|
+
private getKeyString;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* AMT Gateway Client (Direct Sockets based)
|
|
91
|
+
*
|
|
92
|
+
* Connects to an AMT relay to receive multicast data via unicast tunnel.
|
|
93
|
+
* Implements the gateway side of RFC 7450.
|
|
94
|
+
* Supports multiple (S,G) groups over a single AMT tunnel.
|
|
95
|
+
*/
|
|
96
|
+
export declare class AMTGateway {
|
|
97
|
+
private relayAddress;
|
|
98
|
+
private relayPort;
|
|
99
|
+
private groups;
|
|
100
|
+
private onPacket;
|
|
101
|
+
private onStateChange;
|
|
102
|
+
private onError;
|
|
103
|
+
private onLog;
|
|
104
|
+
private state;
|
|
105
|
+
private nonce;
|
|
106
|
+
private responseMAC;
|
|
107
|
+
private relayConfirmedAddress;
|
|
108
|
+
private lastDataTime;
|
|
109
|
+
private stats;
|
|
110
|
+
constructor(options: AMTGatewayOptions);
|
|
111
|
+
/**
|
|
112
|
+
* Generate random nonce
|
|
113
|
+
*/
|
|
114
|
+
private generateNonce;
|
|
115
|
+
/**
|
|
116
|
+
* Set gateway state
|
|
117
|
+
*/
|
|
118
|
+
private setState;
|
|
119
|
+
/**
|
|
120
|
+
* Join a multicast group
|
|
121
|
+
*/
|
|
122
|
+
joinGroup(groupAddress: string, groupPort: number, sourceAddress?: string | null, onPacket?: ((packet: AMTPacketInfo) => void) | null): Promise<string>;
|
|
123
|
+
/**
|
|
124
|
+
* Leave a multicast group
|
|
125
|
+
*/
|
|
126
|
+
leaveGroup(groupAddress: string, sourceAddress?: string | null): Promise<boolean>;
|
|
127
|
+
/**
|
|
128
|
+
* Get list of active groups
|
|
129
|
+
*/
|
|
130
|
+
getGroups(): Array<{
|
|
131
|
+
groupKey: string;
|
|
132
|
+
groupAddress: string;
|
|
133
|
+
sourceAddress: string | null;
|
|
134
|
+
groupPort: number;
|
|
135
|
+
joinedAt: number;
|
|
136
|
+
}>;
|
|
137
|
+
/**
|
|
138
|
+
* Open connection to AMT relay
|
|
139
|
+
*/
|
|
140
|
+
open(): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Close connection
|
|
143
|
+
*/
|
|
144
|
+
close(): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Get current statistics
|
|
147
|
+
*/
|
|
148
|
+
getStats(): typeof this.stats;
|
|
149
|
+
/**
|
|
150
|
+
* Get current state
|
|
151
|
+
*/
|
|
152
|
+
getState(): GatewayState;
|
|
153
|
+
/**
|
|
154
|
+
* Check if gateway is active and receiving data
|
|
155
|
+
*/
|
|
156
|
+
isActive(): boolean;
|
|
157
|
+
}
|
|
158
|
+
export declare const amtGatewayManager: AMTGatewayManager;
|
|
159
|
+
export {};
|
|
160
|
+
//# sourceMappingURL=amt-gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amt-gateway.d.ts","sourceRoot":"","sources":["../src/amt-gateway.ts"],"names":[],"mappings":"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"}
|