Skip to content

Commit

Permalink
Add UDP NAT hole punching, from zoolyka
Browse files Browse the repository at this point in the history
  • Loading branch information
RogerHardiman committed Feb 15, 2023
1 parent 121388a commit 9b6a996
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions lib/RTSPClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ export default class RTSPClient extends EventEmitter {
let setupRes;
let rtpChannel;
let rtcpChannel;
let rtpReceiver: dgram.Socket|null = null; // UDP mode init value
let rtcpReceiver: dgram.Socket|null = null; // UDP mode init value

if (connection === "udp") {
// Create a pair of UDP listeners, even numbered port for RTP
Expand All @@ -308,15 +310,15 @@ export default class RTSPClient extends EventEmitter {
this._nextFreeUDPPort += 2;

const rtpPort = rtpChannel;
const rtpReceiver = dgram.createSocket("udp4");
rtpReceiver = dgram.createSocket("udp4");

rtpReceiver.on("message", (buf, remote) => {
const packet = parseRTPPacket(buf);
this.emit("data", rtpPort, packet.payload, packet);
});

const rtcpPort = rtcpChannel;
const rtcpReceiver = dgram.createSocket("udp4");
rtcpReceiver = dgram.createSocket("udp4");

rtcpReceiver.on("message", (buf, remote) => {
const packet = parseRTCPPacket(buf);
Expand All @@ -329,11 +331,11 @@ export default class RTSPClient extends EventEmitter {
// Block until both UDP sockets are open.

await new Promise((resolve) => {
rtpReceiver.bind(rtpPort, () => resolve({}));
rtpReceiver?.bind(rtpPort, () => resolve({}));
});

await new Promise((resolve) => {
rtcpReceiver.bind(rtcpPort, () => resolve({}));
rtcpReceiver?.bind(rtcpPort, () => resolve({}));
});

const setupHeader = {
Expand Down Expand Up @@ -386,6 +388,16 @@ export default class RTSPClient extends EventEmitter {
);
}

// Patch from zoolyka (Zoltan Hajdu).
// Try to open a hole in the NAT router (to allow incoming UDP packets)
// by send a UDP packet for RTP and RTCP to the remote RTSP server.
// Note, Roger did not have a router that needed this so the feature is untested.
// May be better to change the RTCP message to a Receiver Report, leaving the RTP message as zero bytes
if (connection === "udp" && transport && rtpReceiver && rtcpReceiver) {
rtpReceiver.send(Buffer.from(''), Number(transport.parameters["server_port"].split("-")[0]), hostname);
rtcpReceiver.send(Buffer.from(''), Number(transport.parameters["server_port"].split("-")[1]), hostname);
}

if (headers.Unsupported) {
this._unsupportedExtensions = headers.Unsupported.split(",");
}
Expand Down

0 comments on commit 9b6a996

Please sign in to comment.