krtp
Version:
Node implementation of rdp protocol. RFC 3550
192 lines (191 loc) • 7.55 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Session = exports.WriteRTPStream = exports.ReadRTPStream = void 0;
/*
* +===============================================
* | Author: Parham Alvani (parham.alvani@gmail.com)
* |
* | Creation Date: 01-06-2017
* |
* | File Name: session.ts
* +===============================================
*/
var crypto_1 = require("crypto");
var dgram = __importStar(require("dgram"));
var events_1 = require("events");
var rxjs_1 = require("rxjs");
var Packet_1 = require("./Packet");
var Control_1 = require("./Control");
var stream_1 = require("stream");
var ReadRTPStream = /** @class */ (function (_super) {
__extends(ReadRTPStream, _super);
function ReadRTPStream(session) {
var _this = _super.call(this) || this;
_this.session = session;
_this.session.on("close", function () { return _this.push(null); });
_this.onMessage = function (msg) {
if (!_this.push(msg.payload)) {
_this.session.removeListener("message", _this.onMessage);
}
};
return _this;
}
ReadRTPStream.prototype._read = function (_size) {
if (this.session.listeners("message").indexOf(this.onMessage) === -1) {
this.session.on("message", this.onMessage);
}
};
return ReadRTPStream;
}(stream_1.Readable));
exports.ReadRTPStream = ReadRTPStream;
var WriteRTPStream = /** @class */ (function (_super) {
__extends(WriteRTPStream, _super);
function WriteRTPStream(session, destination) {
var _this = _super.call(this) || this;
_this.session = session;
_this.destination = destination;
return _this;
}
WriteRTPStream.prototype._write = function (chunk, _encoding, callback) {
this.session.send(chunk, this.destination).then(function () { return callback(); }, function (err) { return callback(err); });
};
WriteRTPStream.prototype._destroy = function (err, callback) {
this.session.close();
callback(err);
};
return WriteRTPStream;
}(stream_1.Writable));
exports.WriteRTPStream = WriteRTPStream;
/**
* RTP session: an association among a set of participants
* communicating with RTP.
*/
var Session = /** @class */ (function (_super) {
__extends(Session, _super);
/**
* creates a RTP session with RTCP. please note that the port + 1 is used for rtcp communication.
* @param port - RTP port
* @param packetType - RTP packet type: This field identifies the format of the RTP
* payload and determines its interpretation by the application.
*/
function Session(port, packetType) {
if (packetType === void 0) { packetType = 95; }
var _this = _super.call(this) || this;
_this.port = port;
_this.packetType = packetType;
_this.timestamp = (Date.now() / 1000) | 0;
_this._sequenceNumber = crypto_1.randomBytes(2).readUInt16BE(0);
_this.ssrc = crypto_1.randomBytes(4).readUInt32BE(0);
_this._packetCount = 0;
_this._octetCount = 0;
_this.socket = dgram.createSocket("udp4");
_this.socket.on("message", function (msg, rinfo) {
var packet = Packet_1.Packet.deserialize(msg);
_this.emit("message", packet, rinfo);
});
_this.socket.bind(_this.port, "0.0.0.0");
_this.controlSocket = dgram.createSocket("udp4");
_this.controlSocket.bind(_this.port + 1);
return _this;
}
Object.defineProperty(Session.prototype, "sequenceNumber", {
get: function () {
return this._sequenceNumber;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Session.prototype, "packetCount", {
get: function () {
return this._packetCount;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Session.prototype, "octetCount", {
get: function () {
return this._octetCount;
},
enumerable: false,
configurable: true
});
Session.prototype.sendSR = function (address, timestamp) {
var _this = this;
if (address === void 0) { address = "127.0.0.1"; }
if (timestamp === void 0) { timestamp = ((Date.now() / 1000) | 0) - this.timestamp; }
var packet = new Control_1.ControlSR(this._packetCount, this._octetCount, this.ssrc, timestamp);
return new Promise(function (resolve, reject) {
_this.controlSocket.send(packet.serialize(), _this.port + 1, address, function (err) {
if (err) {
return reject(err);
}
return resolve();
});
});
};
Session.prototype.send = function (payload, address, timestamp) {
var _this = this;
if (address === void 0) { address = "127.0.0.1"; }
if (timestamp === void 0) { timestamp = ((Date.now() / 1000) | 0) - this.timestamp; }
var packet = new Packet_1.Packet(payload, this._sequenceNumber, this.ssrc, timestamp, this.packetType);
this._sequenceNumber = (this._sequenceNumber + 1) % (1 << 16);
this._packetCount += 1;
this._octetCount += payload.length;
return new Promise(function (resolve, reject) {
_this.socket.send(packet.serialize(), _this.port, address, function (err) {
if (err) {
return reject(err);
}
return resolve();
});
});
};
Session.prototype.close = function () {
var _this = this;
this.socket.close(function () {
_this.emit("close");
});
this.controlSocket.close();
};
Object.defineProperty(Session.prototype, "message$", {
get: function () {
return rxjs_1.fromEvent(this, "message", function (msg) { return msg; });
},
enumerable: false,
configurable: true
});
return Session;
}(events_1.EventEmitter));
exports.Session = Session;