werift 0.14.2 → 0.14.5
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/lib/dtls/src/transport.js +10 -1
- package/lib/dtls/src/transport.js.map +1 -1
- package/lib/ice/src/ice.js +1 -1
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/ice/src/stun/protocol.js +8 -1
- package/lib/ice/src/stun/protocol.js.map +1 -1
- package/lib/ice/src/transport.js +9 -12
- package/lib/ice/src/transport.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/ctr.js +1 -5
- package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -1
- package/lib/sctp/src/helper.d.ts +1 -1
- package/lib/sctp/src/helper.js.map +1 -1
- package/lib/sctp/src/sctp.d.ts +7 -2
- package/lib/sctp/src/sctp.js +109 -41
- package/lib/sctp/src/sctp.js.map +1 -1
- package/lib/sctp/src/transport.js +8 -1
- package/lib/sctp/src/transport.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +1 -1
- package/lib/webrtc/src/media/rtpSender.js +6 -6
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/peerConnection.js +11 -3
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +1 -1
- package/lib/webrtc/src/transport/dtls.js +7 -8
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +1 -0
- package/lib/webrtc/src/transport/sctp.js +32 -15
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/package.json +18 -19
- package/src/media/rtpSender.ts +9 -6
- package/src/nonstandard/recorder/writer/webm.ts +1 -1
- package/src/peerConnection.ts +11 -5
- package/src/transport/dtls.ts +7 -7
- package/src/transport/sctp.ts +34 -22
|
@@ -47,9 +47,11 @@ class RTCSctpTransport {
|
|
|
47
47
|
switch (data[0]) {
|
|
48
48
|
case const_1.DATA_CHANNEL_OPEN:
|
|
49
49
|
{
|
|
50
|
-
if (data.length
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
if (data.length < 12) {
|
|
51
|
+
log("DATA_CHANNEL_OPEN data.length not enough");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (!Object.keys(this.dataChannels).includes(streamId.toString())) {
|
|
53
55
|
const [, channelType, , reliability, labelLength, protocolLength,] = jspack_1.jspack.Unpack("!BBHLHH", data);
|
|
54
56
|
let pos = 12;
|
|
55
57
|
const label = data.slice(pos, pos + labelLength).toString("utf8");
|
|
@@ -78,22 +80,27 @@ class RTCSctpTransport {
|
|
|
78
80
|
const channel = new dataChannel_1.RTCDataChannel(this, parameters, false);
|
|
79
81
|
channel.isCreatedByRemote = true;
|
|
80
82
|
this.dataChannels[streamId] = channel;
|
|
81
|
-
this.dataChannelQueue.push([
|
|
82
|
-
channel,
|
|
83
|
-
const_1.WEBRTC_DCEP,
|
|
84
|
-
Buffer.from(jspack_1.jspack.Pack("!B", [const_1.DATA_CHANNEL_ACK])),
|
|
85
|
-
]);
|
|
86
83
|
this.onDataChannel.execute(channel);
|
|
87
84
|
channel.setReadyState("open");
|
|
88
|
-
await this.dataChannelFlush();
|
|
89
85
|
}
|
|
86
|
+
else {
|
|
87
|
+
log("datachannel already opened", "retransmit ack");
|
|
88
|
+
}
|
|
89
|
+
const channel = this.dataChannels[streamId];
|
|
90
|
+
this.dataChannelQueue.push([
|
|
91
|
+
channel,
|
|
92
|
+
const_1.WEBRTC_DCEP,
|
|
93
|
+
Buffer.from(jspack_1.jspack.Pack("!B", [const_1.DATA_CHANNEL_ACK])),
|
|
94
|
+
]);
|
|
95
|
+
await this.dataChannelFlush();
|
|
90
96
|
}
|
|
91
97
|
break;
|
|
92
98
|
case const_1.DATA_CHANNEL_ACK:
|
|
93
|
-
log("DATA_CHANNEL_ACK");
|
|
99
|
+
log("DATA_CHANNEL_ACK", streamId, ppId);
|
|
94
100
|
const channel = this.dataChannels[streamId];
|
|
95
|
-
if (!channel)
|
|
96
|
-
throw new Error();
|
|
101
|
+
if (!channel) {
|
|
102
|
+
throw new Error("channel not found");
|
|
103
|
+
}
|
|
97
104
|
channel.setReadyState("open");
|
|
98
105
|
break;
|
|
99
106
|
}
|
|
@@ -117,8 +124,9 @@ class RTCSctpTransport {
|
|
|
117
124
|
})();
|
|
118
125
|
channel.message.execute(msg);
|
|
119
126
|
channel.emit("message", { data: msg });
|
|
120
|
-
if (channel.onmessage)
|
|
127
|
+
if (channel.onmessage) {
|
|
121
128
|
channel.onmessage({ data: msg });
|
|
129
|
+
}
|
|
122
130
|
}
|
|
123
131
|
}
|
|
124
132
|
};
|
|
@@ -245,13 +253,19 @@ class RTCSctpTransport {
|
|
|
245
253
|
channel.setId(streamId);
|
|
246
254
|
}
|
|
247
255
|
if (protocol === const_1.WEBRTC_DCEP) {
|
|
248
|
-
await this.sctp.send(streamId, protocol, userData
|
|
256
|
+
await this.sctp.send(streamId, protocol, userData, {
|
|
257
|
+
ordered: true,
|
|
258
|
+
});
|
|
249
259
|
}
|
|
250
260
|
else {
|
|
251
261
|
const expiry = channel.maxPacketLifeTime
|
|
252
262
|
? Date.now() + channel.maxPacketLifeTime / 1000
|
|
253
263
|
: undefined;
|
|
254
|
-
await this.sctp.send(streamId, protocol, userData,
|
|
264
|
+
await this.sctp.send(streamId, protocol, userData, {
|
|
265
|
+
expiry,
|
|
266
|
+
maxRetransmits: channel.maxRetransmits,
|
|
267
|
+
ordered: channel.ordered,
|
|
268
|
+
});
|
|
255
269
|
channel.addBufferedAmount(-userData.length);
|
|
256
270
|
}
|
|
257
271
|
}
|
|
@@ -259,6 +273,9 @@ class RTCSctpTransport {
|
|
|
259
273
|
static getCapabilities() {
|
|
260
274
|
return new RTCSctpCapabilities(65536);
|
|
261
275
|
}
|
|
276
|
+
setRemotePort(port) {
|
|
277
|
+
this.sctp.setRemotePort(port);
|
|
278
|
+
}
|
|
262
279
|
async start(remotePort) {
|
|
263
280
|
if (this.isServer) {
|
|
264
281
|
this.dataChannelId = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sctp.js","sourceRoot":"","sources":["../../../../src/transport/sctp.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport { jspack } from \"jspack\";\nimport { Event } from \"rx.mini\";\nimport * as uuid from \"uuid\";\n\nimport { SCTP, SCTP_STATE, Transport } from \"../../../sctp/src\";\nimport {\n DATA_CHANNEL_ACK,\n DATA_CHANNEL_OPEN,\n DATA_CHANNEL_RELIABLE,\n WEBRTC_BINARY,\n WEBRTC_BINARY_EMPTY,\n WEBRTC_DCEP,\n WEBRTC_STRING,\n WEBRTC_STRING_EMPTY,\n} from \"../const\";\nimport {\n DCState,\n RTCDataChannel,\n RTCDataChannelParameters,\n} from \"../dataChannel\";\nimport { RTCDtlsTransport } from \"./dtls\";\n\nconst log = debug(\"werift/webrtc/transport/sctp\");\n\nexport class RTCSctpTransport {\n readonly onDataChannel = new Event<[RTCDataChannel]>();\n readonly uuid = uuid.v4();\n readonly sctp = new SCTP(new BridgeDtls(this.dtlsTransport), this.port);\n mid?: string;\n bundled = false;\n dataChannels: { [key: number]: RTCDataChannel } = {};\n\n private dataChannelQueue: [RTCDataChannel, number, Buffer][] = [];\n private dataChannelId?: number;\n\n constructor(public dtlsTransport: RTCDtlsTransport, public port = 5000) {\n this.sctp.onReceive.subscribe(this.datachannelReceive);\n this.sctp.onReconfigStreams.subscribe((ids: number[]) => {\n ids.forEach((id) => {\n const dc = this.dataChannels[id];\n if (!dc) return;\n // todo fix\n dc.setReadyState(\"closing\");\n dc.setReadyState(\"closed\");\n delete this.dataChannels[id];\n });\n });\n this.sctp.stateChanged.connected.subscribe(() => {\n Object.values(this.dataChannels).forEach((channel) => {\n if (channel.negotiated && channel.readyState !== \"open\") {\n channel.setReadyState(\"open\");\n }\n });\n this.dataChannelFlush();\n });\n this.sctp.stateChanged.closed.subscribe(() => {\n Object.values(this.dataChannels).forEach((dc) => {\n dc.setReadyState(\"closed\");\n });\n this.dataChannels = {};\n });\n this.sctp.onSackReceived = async () => {\n await this.dataChannelFlush();\n };\n\n this.dtlsTransport.onStateChange.subscribe((state) => {\n if (state === \"closed\") {\n this.sctp.setState(SCTP_STATE.CLOSED);\n }\n });\n }\n\n private get isServer() {\n return this.dtlsTransport.iceTransport.role !== \"controlling\";\n }\n\n channelByLabel(label: string) {\n return Object.values(this.dataChannels).find((d) => d.label === label);\n }\n\n private datachannelReceive = async (\n streamId: number,\n ppId: number,\n data: Buffer\n ) => {\n if (ppId === WEBRTC_DCEP && data.length > 0) {\n log(\"DCEP\", streamId, ppId, data);\n switch (data[0]) {\n case DATA_CHANNEL_OPEN:\n {\n if (data.length >= 12) {\n if (Object.keys(this.dataChannels).includes(streamId.toString()))\n throw new Error();\n\n const [\n ,\n channelType,\n ,\n reliability,\n labelLength,\n protocolLength,\n ] = jspack.Unpack(\"!BBHLHH\", data);\n\n let pos = 12;\n const label = data.slice(pos, pos + labelLength).toString(\"utf8\");\n pos += labelLength;\n const protocol = data\n .slice(pos, pos + protocolLength)\n .toString(\"utf8\");\n\n log(\"DATA_CHANNEL_OPEN\", {\n channelType,\n reliability,\n streamId,\n label,\n protocol,\n });\n\n const maxRetransmits =\n (channelType & 0x03) === 1 ? reliability : undefined;\n const maxPacketLifeTime =\n (channelType & 0x03) === 2 ? reliability : undefined;\n\n // # register channel\n const parameters = new RTCDataChannelParameters({\n label,\n ordered: (channelType & 0x80) === 0,\n maxPacketLifeTime,\n maxRetransmits,\n protocol,\n id: streamId,\n });\n const channel = new RTCDataChannel(this, parameters, false);\n channel.isCreatedByRemote = true;\n this.dataChannels[streamId] = channel;\n\n this.dataChannelQueue.push([\n channel,\n WEBRTC_DCEP,\n Buffer.from(jspack.Pack(\"!B\", [DATA_CHANNEL_ACK])),\n ]);\n\n this.onDataChannel.execute(channel);\n channel.setReadyState(\"open\");\n\n await this.dataChannelFlush();\n }\n }\n break;\n case DATA_CHANNEL_ACK:\n log(\"DATA_CHANNEL_ACK\");\n const channel = this.dataChannels[streamId];\n if (!channel) throw new Error();\n channel.setReadyState(\"open\");\n break;\n }\n } else {\n const channel = this.dataChannels[streamId];\n if (channel) {\n const msg = (() => {\n switch (ppId) {\n case WEBRTC_STRING:\n return data.toString(\"utf8\");\n case WEBRTC_STRING_EMPTY:\n return \"\";\n case WEBRTC_BINARY:\n return data;\n case WEBRTC_BINARY_EMPTY:\n return Buffer.from([]);\n default:\n throw new Error();\n }\n })();\n channel.message.execute(msg);\n channel.emit(\"message\", { data: msg });\n if (channel.onmessage) channel.onmessage({ data: msg });\n }\n }\n };\n\n dataChannelAddNegotiated(channel: RTCDataChannel) {\n if (channel.id == undefined) {\n throw new Error();\n }\n if (this.dataChannels[channel.id]) {\n throw new Error();\n }\n\n this.dataChannels[channel.id] = channel;\n\n if (this.sctp.associationState === SCTP_STATE.ESTABLISHED) {\n channel.setReadyState(\"open\");\n }\n }\n\n dataChannelOpen(channel: RTCDataChannel) {\n if (channel.id) {\n if (this.dataChannels[channel.id])\n throw new Error(\n `Data channel with ID ${channel.id} already registered`\n );\n this.dataChannels[channel.id] = channel;\n }\n\n let channelType = DATA_CHANNEL_RELIABLE;\n const priority = 0;\n let reliability = 0;\n\n if (!channel.ordered) {\n channelType = 0x80;\n }\n if (channel.maxRetransmits) {\n channelType = 1;\n reliability = channel.maxRetransmits;\n } else if (channel.maxPacketLifeTime) {\n channelType = 2;\n reliability = channel.maxPacketLifeTime;\n }\n\n // 5.1. DATA_CHANNEL_OPEN Message\n const data = jspack.Pack(\"!BBHLHH\", [\n DATA_CHANNEL_OPEN,\n channelType,\n priority,\n reliability,\n channel.label.length,\n channel.protocol.length,\n ]);\n const send = Buffer.concat([\n Buffer.from(data),\n Buffer.from(channel.label, \"utf8\"),\n Buffer.from(channel.protocol, \"utf8\"),\n ]);\n this.dataChannelQueue.push([channel, WEBRTC_DCEP, send]);\n this.dataChannelFlush();\n }\n\n private async dataChannelFlush() {\n // \"\"\"\n // Try to flush buffered data to the SCTP layer.\n\n // We wait until the association is established, as we need to know\n // whether we are a client or a server to correctly assign an odd/even ID\n // to the data channels.\n // \"\"\"\n\n if (this.sctp.associationState != SCTP_STATE.ESTABLISHED) return;\n if (this.sctp.outboundQueue.length > 0) return;\n\n while (this.dataChannelQueue.length > 0) {\n const [channel, protocol, userData] = this.dataChannelQueue.shift()!;\n\n let streamId = channel.id;\n if (streamId === undefined) {\n streamId = this.dataChannelId!;\n while (Object.keys(this.dataChannels).includes(streamId.toString())) {\n streamId += 2;\n }\n this.dataChannels[streamId] = channel;\n channel.setId(streamId);\n }\n\n if (protocol === WEBRTC_DCEP) {\n await this.sctp.send(streamId, protocol, userData);\n } else {\n const expiry = channel.maxPacketLifeTime\n ? Date.now() + channel.maxPacketLifeTime / 1000\n : undefined;\n\n await this.sctp.send(\n streamId,\n protocol,\n userData,\n expiry,\n channel.maxRetransmits,\n channel.ordered\n );\n channel.addBufferedAmount(-userData.length);\n }\n }\n }\n\n datachannelSend = (channel: RTCDataChannel, data: Buffer | string) => {\n channel.addBufferedAmount(data.length);\n\n this.dataChannelQueue.push(\n typeof data === \"string\"\n ? [channel, WEBRTC_STRING, Buffer.from(data)]\n : [channel, WEBRTC_BINARY, data]\n );\n\n if (this.sctp.associationState !== SCTP_STATE.ESTABLISHED) {\n log(\"sctp not established\", this.sctp.associationState);\n }\n\n this.dataChannelFlush();\n };\n\n static getCapabilities() {\n return new RTCSctpCapabilities(65536);\n }\n\n async start(remotePort: number) {\n if (this.isServer) {\n this.dataChannelId = 0;\n } else {\n this.dataChannelId = 1;\n }\n this.sctp.isServer = this.isServer;\n\n await this.sctp.start(remotePort);\n }\n\n async stop() {\n this.dtlsTransport.dataReceiver = () => {};\n await this.sctp.stop();\n }\n\n dataChannelClose(channel: RTCDataChannel) {\n if (!([\"closing\", \"closed\"] as DCState[]).includes(channel.readyState)) {\n channel.setReadyState(\"closing\");\n\n if (this.sctp.associationState === SCTP_STATE.ESTABLISHED) {\n this.sctp.reconfigQueue.push(channel.id);\n if (this.sctp.reconfigQueue.length === 1) {\n this.sctp.transmitReconfigRequest();\n }\n } else {\n this.dataChannelQueue = this.dataChannelQueue.filter(\n (queueItem) => queueItem[0].id !== channel.id\n );\n if (channel.id) {\n delete this.dataChannels[channel.id];\n }\n channel.setReadyState(\"closed\");\n }\n }\n }\n}\n\nexport class RTCSctpCapabilities {\n constructor(public maxMessageSize: number) {}\n}\n\nclass BridgeDtls implements Transport {\n constructor(private dtls: RTCDtlsTransport) {}\n set onData(onData: (buf: Buffer) => void) {\n this.dtls.dataReceiver = onData;\n }\n readonly send = this.dtls.sendData;\n close() {}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sctp.js","sourceRoot":"","sources":["../../../../src/transport/sctp.ts"],"names":[],"mappings":"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","sourcesContent":["import debug from \"debug\";\nimport { jspack } from \"jspack\";\nimport { Event } from \"rx.mini\";\nimport * as uuid from \"uuid\";\n\nimport { SCTP, SCTP_STATE, Transport } from \"../../../sctp/src\";\nimport {\n DATA_CHANNEL_ACK,\n DATA_CHANNEL_OPEN,\n DATA_CHANNEL_RELIABLE,\n WEBRTC_BINARY,\n WEBRTC_BINARY_EMPTY,\n WEBRTC_DCEP,\n WEBRTC_STRING,\n WEBRTC_STRING_EMPTY,\n} from \"../const\";\nimport {\n DCState,\n RTCDataChannel,\n RTCDataChannelParameters,\n} from \"../dataChannel\";\nimport { RTCDtlsTransport } from \"./dtls\";\n\nconst log = debug(\"werift/webrtc/transport/sctp\");\n\nexport class RTCSctpTransport {\n readonly onDataChannel = new Event<[RTCDataChannel]>();\n readonly uuid = uuid.v4();\n readonly sctp = new SCTP(new BridgeDtls(this.dtlsTransport), this.port);\n mid?: string;\n bundled = false;\n dataChannels: { [key: number]: RTCDataChannel } = {};\n\n private dataChannelQueue: [RTCDataChannel, number, Buffer][] = [];\n private dataChannelId?: number;\n\n constructor(public dtlsTransport: RTCDtlsTransport, public port = 5000) {\n this.sctp.onReceive.subscribe(this.datachannelReceive);\n this.sctp.onReconfigStreams.subscribe((ids: number[]) => {\n ids.forEach((id) => {\n const dc = this.dataChannels[id];\n if (!dc) return;\n // todo fix\n dc.setReadyState(\"closing\");\n dc.setReadyState(\"closed\");\n delete this.dataChannels[id];\n });\n });\n this.sctp.stateChanged.connected.subscribe(() => {\n Object.values(this.dataChannels).forEach((channel) => {\n if (channel.negotiated && channel.readyState !== \"open\") {\n channel.setReadyState(\"open\");\n }\n });\n this.dataChannelFlush();\n });\n this.sctp.stateChanged.closed.subscribe(() => {\n Object.values(this.dataChannels).forEach((dc) => {\n dc.setReadyState(\"closed\");\n });\n this.dataChannels = {};\n });\n this.sctp.onSackReceived = async () => {\n await this.dataChannelFlush();\n };\n\n this.dtlsTransport.onStateChange.subscribe((state) => {\n if (state === \"closed\") {\n this.sctp.setState(SCTP_STATE.CLOSED);\n }\n });\n }\n\n private get isServer() {\n return this.dtlsTransport.iceTransport.role !== \"controlling\";\n }\n\n channelByLabel(label: string) {\n return Object.values(this.dataChannels).find((d) => d.label === label);\n }\n\n private datachannelReceive = async (\n streamId: number,\n ppId: number,\n data: Buffer\n ) => {\n if (ppId === WEBRTC_DCEP && data.length > 0) {\n log(\"DCEP\", streamId, ppId, data);\n switch (data[0]) {\n case DATA_CHANNEL_OPEN:\n {\n if (data.length < 12) {\n log(\"DATA_CHANNEL_OPEN data.length not enough\");\n return;\n }\n\n if (!Object.keys(this.dataChannels).includes(streamId.toString())) {\n const [\n ,\n channelType,\n ,\n reliability,\n labelLength,\n protocolLength,\n ] = jspack.Unpack(\"!BBHLHH\", data);\n\n let pos = 12;\n const label = data.slice(pos, pos + labelLength).toString(\"utf8\");\n pos += labelLength;\n const protocol = data\n .slice(pos, pos + protocolLength)\n .toString(\"utf8\");\n\n log(\"DATA_CHANNEL_OPEN\", {\n channelType,\n reliability,\n streamId,\n label,\n protocol,\n });\n\n const maxRetransmits =\n (channelType & 0x03) === 1 ? reliability : undefined;\n const maxPacketLifeTime =\n (channelType & 0x03) === 2 ? reliability : undefined;\n\n // # register channel\n const parameters = new RTCDataChannelParameters({\n label,\n ordered: (channelType & 0x80) === 0,\n maxPacketLifeTime,\n maxRetransmits,\n protocol,\n id: streamId,\n });\n const channel = new RTCDataChannel(this, parameters, false);\n channel.isCreatedByRemote = true;\n this.dataChannels[streamId] = channel;\n\n this.onDataChannel.execute(channel);\n channel.setReadyState(\"open\");\n } else {\n log(\"datachannel already opened\", \"retransmit ack\");\n }\n\n const channel = this.dataChannels[streamId];\n this.dataChannelQueue.push([\n channel,\n WEBRTC_DCEP,\n Buffer.from(jspack.Pack(\"!B\", [DATA_CHANNEL_ACK])),\n ]);\n await this.dataChannelFlush();\n }\n break;\n case DATA_CHANNEL_ACK:\n log(\"DATA_CHANNEL_ACK\", streamId, ppId);\n const channel = this.dataChannels[streamId];\n if (!channel) {\n throw new Error(\"channel not found\");\n }\n channel.setReadyState(\"open\");\n break;\n }\n } else {\n const channel = this.dataChannels[streamId];\n if (channel) {\n const msg = (() => {\n switch (ppId) {\n case WEBRTC_STRING:\n return data.toString(\"utf8\");\n case WEBRTC_STRING_EMPTY:\n return \"\";\n case WEBRTC_BINARY:\n return data;\n case WEBRTC_BINARY_EMPTY:\n return Buffer.from([]);\n default:\n throw new Error();\n }\n })();\n\n channel.message.execute(msg);\n channel.emit(\"message\", { data: msg });\n if (channel.onmessage) {\n channel.onmessage({ data: msg });\n }\n }\n }\n };\n\n dataChannelAddNegotiated(channel: RTCDataChannel) {\n if (channel.id == undefined) {\n throw new Error();\n }\n if (this.dataChannels[channel.id]) {\n throw new Error();\n }\n\n this.dataChannels[channel.id] = channel;\n\n if (this.sctp.associationState === SCTP_STATE.ESTABLISHED) {\n channel.setReadyState(\"open\");\n }\n }\n\n dataChannelOpen(channel: RTCDataChannel) {\n if (channel.id) {\n if (this.dataChannels[channel.id])\n throw new Error(\n `Data channel with ID ${channel.id} already registered`\n );\n this.dataChannels[channel.id] = channel;\n }\n\n let channelType = DATA_CHANNEL_RELIABLE;\n const priority = 0;\n let reliability = 0;\n\n if (!channel.ordered) {\n channelType = 0x80;\n }\n if (channel.maxRetransmits) {\n channelType = 1;\n reliability = channel.maxRetransmits;\n } else if (channel.maxPacketLifeTime) {\n channelType = 2;\n reliability = channel.maxPacketLifeTime;\n }\n\n // 5.1. DATA_CHANNEL_OPEN Message\n const data = jspack.Pack(\"!BBHLHH\", [\n DATA_CHANNEL_OPEN,\n channelType,\n priority,\n reliability,\n channel.label.length,\n channel.protocol.length,\n ]);\n const send = Buffer.concat([\n Buffer.from(data),\n Buffer.from(channel.label, \"utf8\"),\n Buffer.from(channel.protocol, \"utf8\"),\n ]);\n this.dataChannelQueue.push([channel, WEBRTC_DCEP, send]);\n this.dataChannelFlush();\n }\n\n private async dataChannelFlush() {\n // \"\"\"\n // Try to flush buffered data to the SCTP layer.\n\n // We wait until the association is established, as we need to know\n // whether we are a client or a server to correctly assign an odd/even ID\n // to the data channels.\n // \"\"\"\n\n if (this.sctp.associationState != SCTP_STATE.ESTABLISHED) return;\n if (this.sctp.outboundQueue.length > 0) return;\n\n while (this.dataChannelQueue.length > 0) {\n const [channel, protocol, userData] = this.dataChannelQueue.shift()!;\n\n let streamId = channel.id;\n if (streamId === undefined) {\n streamId = this.dataChannelId!;\n while (Object.keys(this.dataChannels).includes(streamId.toString())) {\n streamId += 2;\n }\n this.dataChannels[streamId] = channel;\n channel.setId(streamId);\n }\n\n if (protocol === WEBRTC_DCEP) {\n await this.sctp.send(streamId, protocol, userData, {\n ordered: true,\n });\n } else {\n const expiry = channel.maxPacketLifeTime\n ? Date.now() + channel.maxPacketLifeTime / 1000\n : undefined;\n\n await this.sctp.send(streamId, protocol, userData, {\n expiry,\n maxRetransmits: channel.maxRetransmits,\n ordered: channel.ordered,\n });\n channel.addBufferedAmount(-userData.length);\n }\n }\n }\n\n datachannelSend = (channel: RTCDataChannel, data: Buffer | string) => {\n channel.addBufferedAmount(data.length);\n\n this.dataChannelQueue.push(\n typeof data === \"string\"\n ? [channel, WEBRTC_STRING, Buffer.from(data)]\n : [channel, WEBRTC_BINARY, data]\n );\n\n if (this.sctp.associationState !== SCTP_STATE.ESTABLISHED) {\n log(\"sctp not established\", this.sctp.associationState);\n }\n\n this.dataChannelFlush();\n };\n\n static getCapabilities() {\n return new RTCSctpCapabilities(65536);\n }\n\n setRemotePort(port: number) {\n this.sctp.setRemotePort(port);\n }\n\n async start(remotePort: number) {\n if (this.isServer) {\n this.dataChannelId = 0;\n } else {\n this.dataChannelId = 1;\n }\n this.sctp.isServer = this.isServer;\n\n await this.sctp.start(remotePort);\n }\n\n async stop() {\n this.dtlsTransport.dataReceiver = () => {};\n await this.sctp.stop();\n }\n\n dataChannelClose(channel: RTCDataChannel) {\n if (!([\"closing\", \"closed\"] as DCState[]).includes(channel.readyState)) {\n channel.setReadyState(\"closing\");\n\n if (this.sctp.associationState === SCTP_STATE.ESTABLISHED) {\n this.sctp.reconfigQueue.push(channel.id);\n if (this.sctp.reconfigQueue.length === 1) {\n this.sctp.transmitReconfigRequest();\n }\n } else {\n this.dataChannelQueue = this.dataChannelQueue.filter(\n (queueItem) => queueItem[0].id !== channel.id\n );\n if (channel.id) {\n delete this.dataChannels[channel.id];\n }\n channel.setReadyState(\"closed\");\n }\n }\n }\n}\n\nexport class RTCSctpCapabilities {\n constructor(public maxMessageSize: number) {}\n}\n\nclass BridgeDtls implements Transport {\n constructor(private dtls: RTCDtlsTransport) {}\n set onData(onData: (buf: Buffer) => void) {\n this.dtls.dataReceiver = onData;\n }\n readonly send = this.dtls.sendData;\n close() {}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "werift",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.5",
|
|
4
4
|
"description": "WebRTC Implementation for TypeScript (Node.js)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"WebRTC",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "rm -rf lib && yarn format && tsc -p ./tsconfig.production.json",
|
|
26
26
|
"depcheck": "npx depcheck --ignores='@typescript-eslint/*,eslint-*'",
|
|
27
|
+
"deploy": "yarn build && yarn publish",
|
|
27
28
|
"doc": "rm -rf doc && typedoc --out doc ./src/index.ts",
|
|
28
29
|
"format": "yarn unused && yarn lint && prettier --write src/**/*.ts",
|
|
29
30
|
"lint": "eslint ./src --fix",
|
|
@@ -39,11 +40,10 @@
|
|
|
39
40
|
"@peculiar/x509": "^1.2.2",
|
|
40
41
|
"@shinyoshiaki/ebml-builder": "^0.0.1",
|
|
41
42
|
"aes-js": "^3.1.2",
|
|
42
|
-
"big-integer": "^1.6.49",
|
|
43
43
|
"binary-data": "^0.6.0",
|
|
44
44
|
"buffer-crc32": "^0.2.13",
|
|
45
|
-
"date-fns": "^2.
|
|
46
|
-
"debug": "^4.3.
|
|
45
|
+
"date-fns": "^2.27.0",
|
|
46
|
+
"debug": "^4.3.3",
|
|
47
47
|
"elliptic": "^6.5.3",
|
|
48
48
|
"int64-buffer": "^1.0.1",
|
|
49
49
|
"ip": "^1.1.5",
|
|
@@ -58,25 +58,24 @@
|
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@types/aes-js": "^3.1.1",
|
|
61
|
-
"@types/big-integer": "^0.0.31",
|
|
62
61
|
"@types/buffer-crc32": "^0.2.0",
|
|
63
62
|
"@types/debug": "^4.1.7",
|
|
64
|
-
"@types/elliptic": "^6.4.
|
|
63
|
+
"@types/elliptic": "^6.4.14",
|
|
65
64
|
"@types/ip": "^1.1.0",
|
|
66
|
-
"@types/jest": "^27.0.
|
|
67
|
-
"@types/lodash": "^4.14.
|
|
68
|
-
"@types/node": "^
|
|
69
|
-
"@types/uuid": "^8.3.
|
|
70
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
71
|
-
"@typescript-eslint/parser": "^
|
|
65
|
+
"@types/jest": "^27.0.3",
|
|
66
|
+
"@types/lodash": "^4.14.178",
|
|
67
|
+
"@types/node": "^17.0.0",
|
|
68
|
+
"@types/uuid": "^8.3.3",
|
|
69
|
+
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
|
70
|
+
"@typescript-eslint/parser": "^5.7.0",
|
|
72
71
|
"eslint-plugin-prettier": "^4.0.0",
|
|
73
|
-
"jest": "^27.
|
|
74
|
-
"node-actionlint": "^1.2.
|
|
75
|
-
"prettier": "^2.
|
|
76
|
-
"ts-jest": "^27.
|
|
77
|
-
"ts-node": "^10.
|
|
78
|
-
"typedoc": "^0.22.
|
|
79
|
-
"typescript": "^4.4
|
|
72
|
+
"jest": "^27.4.5",
|
|
73
|
+
"node-actionlint": "^1.2.1",
|
|
74
|
+
"prettier": "^2.5.1",
|
|
75
|
+
"ts-jest": "^27.1.1",
|
|
76
|
+
"ts-node": "^10.4.0",
|
|
77
|
+
"typedoc": "^0.22.10",
|
|
78
|
+
"typescript": "^4.5.4"
|
|
80
79
|
},
|
|
81
80
|
"engines": {
|
|
82
81
|
"node": ">=15"
|
package/src/media/rtpSender.ts
CHANGED
|
@@ -161,8 +161,8 @@ export class RTCRtpSender {
|
|
|
161
161
|
|
|
162
162
|
track.id = this.trackId;
|
|
163
163
|
|
|
164
|
-
const { unSubscribe } = track.onReceiveRtp.subscribe((rtp) => {
|
|
165
|
-
this.sendRtp(rtp);
|
|
164
|
+
const { unSubscribe } = track.onReceiveRtp.subscribe(async (rtp) => {
|
|
165
|
+
await this.sendRtp(rtp);
|
|
166
166
|
});
|
|
167
167
|
this.track = track;
|
|
168
168
|
this.disposeTrack = unSubscribe;
|
|
@@ -266,7 +266,7 @@ export class RTCRtpSender {
|
|
|
266
266
|
log("replaceRTP", this.sequenceNumber, sequenceNumber, this.seqOffset);
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
sendRtp(rtp: Buffer | RtpPacket) {
|
|
269
|
+
async sendRtp(rtp: Buffer | RtpPacket) {
|
|
270
270
|
if (this.dtlsTransport.state !== "connected" || !this.codec) {
|
|
271
271
|
return;
|
|
272
272
|
}
|
|
@@ -345,7 +345,7 @@ export class RTCRtpSender {
|
|
|
345
345
|
rtpPayload = red.serialize();
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
const size = this.dtlsTransport.sendRtp(rtpPayload, header);
|
|
348
|
+
const size = await this.dtlsTransport.sendRtp(rtpPayload, header);
|
|
349
349
|
|
|
350
350
|
this.runRtcp();
|
|
351
351
|
const sentInfo: SentInfo = {
|
|
@@ -391,7 +391,7 @@ export class RTCRtpSender {
|
|
|
391
391
|
case GenericNack.count:
|
|
392
392
|
{
|
|
393
393
|
const feedback = packet.feedback as GenericNack;
|
|
394
|
-
feedback.lost.forEach((seqNum) => {
|
|
394
|
+
feedback.lost.forEach(async (seqNum) => {
|
|
395
395
|
let packet = this.rtpCache.find(
|
|
396
396
|
(rtp) => rtp.header.sequenceNumber === seqNum
|
|
397
397
|
);
|
|
@@ -408,7 +408,10 @@ export class RTCRtpSender {
|
|
|
408
408
|
1
|
|
409
409
|
);
|
|
410
410
|
}
|
|
411
|
-
this.dtlsTransport.sendRtp(
|
|
411
|
+
await this.dtlsTransport.sendRtp(
|
|
412
|
+
packet.payload,
|
|
413
|
+
packet.header
|
|
414
|
+
);
|
|
412
415
|
}
|
|
413
416
|
});
|
|
414
417
|
this.onGenericNack.execute(feedback);
|
|
@@ -15,7 +15,7 @@ export class WebmFactory extends MediaWriter {
|
|
|
15
15
|
start(tracks: MediaStreamTrack[]) {
|
|
16
16
|
this.webm = new WebmOutput(
|
|
17
17
|
fs,
|
|
18
|
-
|
|
18
|
+
this.path,
|
|
19
19
|
tracks.map((track, i) => {
|
|
20
20
|
const trackNumber = i + 1;
|
|
21
21
|
const payloadType = track.codec!.payloadType;
|
package/src/peerConnection.ts
CHANGED
|
@@ -318,8 +318,9 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
318
318
|
};
|
|
319
319
|
const settings: Required<typeof base> = { ...base, ...options } as any;
|
|
320
320
|
|
|
321
|
-
if (settings.maxPacketLifeTime && settings.maxRetransmits)
|
|
321
|
+
if (settings.maxPacketLifeTime && settings.maxRetransmits) {
|
|
322
322
|
throw new Error("can not select both");
|
|
323
|
+
}
|
|
323
324
|
|
|
324
325
|
if (!this.sctpTransport) {
|
|
325
326
|
this.sctpTransport = this.createSctpTransport();
|
|
@@ -514,6 +515,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
514
515
|
|
|
515
516
|
// connect transports
|
|
516
517
|
if (description.type === "answer") {
|
|
518
|
+
log("callee start connect");
|
|
517
519
|
this.connect().catch((err) => {
|
|
518
520
|
log("connect failed", err);
|
|
519
521
|
this.setConnectionState("failed");
|
|
@@ -564,6 +566,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
564
566
|
await this.sctpTransport.start(this.sctpRemotePort);
|
|
565
567
|
await this.sctpTransport.sctp.stateChanged.connected.asPromise();
|
|
566
568
|
}
|
|
569
|
+
log("sctp connected");
|
|
567
570
|
|
|
568
571
|
this.masterTransportEstablished = true;
|
|
569
572
|
this.setConnectionState("connected");
|
|
@@ -738,16 +741,18 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
738
741
|
|
|
739
742
|
transceiver.receiver.setupTWCC(remoteMedia.ssrc[0]?.ssrc);
|
|
740
743
|
} else if (remoteMedia.kind === "application") {
|
|
744
|
+
// # configure sctp
|
|
745
|
+
this.sctpRemotePort = remoteMedia.sctpPort;
|
|
746
|
+
if (!this.sctpRemotePort) {
|
|
747
|
+
throw new Error("sctpRemotePort not exist");
|
|
748
|
+
}
|
|
741
749
|
if (!this.sctpTransport) {
|
|
742
750
|
this.sctpTransport = this.createSctpTransport();
|
|
743
751
|
}
|
|
744
|
-
|
|
752
|
+
this.sctpTransport.setRemotePort(this.sctpRemotePort);
|
|
745
753
|
if (!this.sctpTransport.mid) {
|
|
746
754
|
this.sctpTransport.mid = remoteMedia.rtp.muxId;
|
|
747
755
|
}
|
|
748
|
-
|
|
749
|
-
// # configure sctp
|
|
750
|
-
this.sctpRemotePort = remoteMedia.sctpPort;
|
|
751
756
|
}
|
|
752
757
|
|
|
753
758
|
if (remoteMedia.iceParams && remoteMedia.dtlsParams) {
|
|
@@ -779,6 +784,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
779
784
|
|
|
780
785
|
// connect transports
|
|
781
786
|
if (remoteSdp.type === "answer") {
|
|
787
|
+
log("caller start connect");
|
|
782
788
|
this.connect().catch((err) => {
|
|
783
789
|
log("connect failed", err);
|
|
784
790
|
this.setConnectionState("failed");
|
package/src/transport/dtls.ts
CHANGED
|
@@ -194,20 +194,20 @@ export class RTCDtlsTransport {
|
|
|
194
194
|
await this.dtls.send(data);
|
|
195
195
|
};
|
|
196
196
|
|
|
197
|
-
sendRtp(payload: Buffer, header: RtpHeader) {
|
|
197
|
+
async sendRtp(payload: Buffer, header: RtpHeader) {
|
|
198
198
|
const enc = this.srtp.encrypt(payload, header);
|
|
199
|
-
this.iceTransport.connection.send(enc)
|
|
199
|
+
await this.iceTransport.connection.send(enc).catch((err: Error) => {
|
|
200
|
+
log("sendRtp failed", err.message);
|
|
201
|
+
});
|
|
200
202
|
return enc.length;
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
async sendRtcp(packets: RtcpPacket[]) {
|
|
204
206
|
const payload = Buffer.concat(packets.map((packet) => packet.serialize()));
|
|
205
207
|
const enc = this.srtcp.encrypt(payload);
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
throw new Error("ice");
|
|
210
|
-
}
|
|
208
|
+
await this.iceTransport.connection.send(enc).catch((err: Error) => {
|
|
209
|
+
log("sendRtcp failed", err.message);
|
|
210
|
+
});
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
private setState(state: DtlsState) {
|
package/src/transport/sctp.ts
CHANGED
|
@@ -89,10 +89,12 @@ export class RTCSctpTransport {
|
|
|
89
89
|
switch (data[0]) {
|
|
90
90
|
case DATA_CHANNEL_OPEN:
|
|
91
91
|
{
|
|
92
|
-
if (data.length
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
if (data.length < 12) {
|
|
93
|
+
log("DATA_CHANNEL_OPEN data.length not enough");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
95
96
|
|
|
97
|
+
if (!Object.keys(this.dataChannels).includes(streamId.toString())) {
|
|
96
98
|
const [
|
|
97
99
|
,
|
|
98
100
|
channelType,
|
|
@@ -135,23 +137,27 @@ export class RTCSctpTransport {
|
|
|
135
137
|
channel.isCreatedByRemote = true;
|
|
136
138
|
this.dataChannels[streamId] = channel;
|
|
137
139
|
|
|
138
|
-
this.dataChannelQueue.push([
|
|
139
|
-
channel,
|
|
140
|
-
WEBRTC_DCEP,
|
|
141
|
-
Buffer.from(jspack.Pack("!B", [DATA_CHANNEL_ACK])),
|
|
142
|
-
]);
|
|
143
|
-
|
|
144
140
|
this.onDataChannel.execute(channel);
|
|
145
141
|
channel.setReadyState("open");
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
} else {
|
|
143
|
+
log("datachannel already opened", "retransmit ack");
|
|
148
144
|
}
|
|
145
|
+
|
|
146
|
+
const channel = this.dataChannels[streamId];
|
|
147
|
+
this.dataChannelQueue.push([
|
|
148
|
+
channel,
|
|
149
|
+
WEBRTC_DCEP,
|
|
150
|
+
Buffer.from(jspack.Pack("!B", [DATA_CHANNEL_ACK])),
|
|
151
|
+
]);
|
|
152
|
+
await this.dataChannelFlush();
|
|
149
153
|
}
|
|
150
154
|
break;
|
|
151
155
|
case DATA_CHANNEL_ACK:
|
|
152
|
-
log("DATA_CHANNEL_ACK");
|
|
156
|
+
log("DATA_CHANNEL_ACK", streamId, ppId);
|
|
153
157
|
const channel = this.dataChannels[streamId];
|
|
154
|
-
if (!channel)
|
|
158
|
+
if (!channel) {
|
|
159
|
+
throw new Error("channel not found");
|
|
160
|
+
}
|
|
155
161
|
channel.setReadyState("open");
|
|
156
162
|
break;
|
|
157
163
|
}
|
|
@@ -172,9 +178,12 @@ export class RTCSctpTransport {
|
|
|
172
178
|
throw new Error();
|
|
173
179
|
}
|
|
174
180
|
})();
|
|
181
|
+
|
|
175
182
|
channel.message.execute(msg);
|
|
176
183
|
channel.emit("message", { data: msg });
|
|
177
|
-
if (channel.onmessage)
|
|
184
|
+
if (channel.onmessage) {
|
|
185
|
+
channel.onmessage({ data: msg });
|
|
186
|
+
}
|
|
178
187
|
}
|
|
179
188
|
}
|
|
180
189
|
};
|
|
@@ -262,20 +271,19 @@ export class RTCSctpTransport {
|
|
|
262
271
|
}
|
|
263
272
|
|
|
264
273
|
if (protocol === WEBRTC_DCEP) {
|
|
265
|
-
await this.sctp.send(streamId, protocol, userData
|
|
274
|
+
await this.sctp.send(streamId, protocol, userData, {
|
|
275
|
+
ordered: true,
|
|
276
|
+
});
|
|
266
277
|
} else {
|
|
267
278
|
const expiry = channel.maxPacketLifeTime
|
|
268
279
|
? Date.now() + channel.maxPacketLifeTime / 1000
|
|
269
280
|
: undefined;
|
|
270
281
|
|
|
271
|
-
await this.sctp.send(
|
|
272
|
-
streamId,
|
|
273
|
-
protocol,
|
|
274
|
-
userData,
|
|
282
|
+
await this.sctp.send(streamId, protocol, userData, {
|
|
275
283
|
expiry,
|
|
276
|
-
channel.maxRetransmits,
|
|
277
|
-
channel.ordered
|
|
278
|
-
);
|
|
284
|
+
maxRetransmits: channel.maxRetransmits,
|
|
285
|
+
ordered: channel.ordered,
|
|
286
|
+
});
|
|
279
287
|
channel.addBufferedAmount(-userData.length);
|
|
280
288
|
}
|
|
281
289
|
}
|
|
@@ -301,6 +309,10 @@ export class RTCSctpTransport {
|
|
|
301
309
|
return new RTCSctpCapabilities(65536);
|
|
302
310
|
}
|
|
303
311
|
|
|
312
|
+
setRemotePort(port: number) {
|
|
313
|
+
this.sctp.setRemotePort(port);
|
|
314
|
+
}
|
|
315
|
+
|
|
304
316
|
async start(remotePort: number) {
|
|
305
317
|
if (this.isServer) {
|
|
306
318
|
this.dataChannelId = 0;
|