agsh / onvif

ONVIF node.js implementation
http://agsh.github.io/onvif/
MIT License
699 stars 240 forks source link

RTSP address in getstreamuri returns the internal 192.168.x.x address of camera #170

Open RogerHardiman opened 4 years ago

RogerHardiman commented 4 years ago

Hi CONFIG:- IP camera at 192.168.1.1 on an internal network. External broadband connection has a static IP and port forwards Port 80 and Port 554 to the camera

Using Options.preserveAddress we can make the library ignore Xaddrs that say 192.168.1.1 but the RTSP address returned from getStreamuri is still 192.168.1.1

FIX:- check the URL in getstreamuri and re-write it with a modifed _parseUrl that keeps the port but changes the hostname I've done a local fix and need to make a PR so this is a reminder to myself

RogerHardiman commented 4 years ago

while we are at it, the URL for the snapshots will need a re-write of the URL as well when preserveAddress is true

RogerHardiman commented 4 years ago
    Cam.prototype.getStreamUri = function (options, callback) {
        if (callback === undefined) { callback = options; options = {}; }
        this._request({
            service: 'media'
            , body: this._envelopeHeader() +
                '<GetStreamUri xmlns="http://www.onvif.org/ver10/media/wsdl">' +
                '<StreamSetup>' +
                '<Stream xmlns="http://www.onvif.org/ver10/schema">' + (options.stream || 'RTP-Unicast') + '</Stream>' +
                '<Transport xmlns="http://www.onvif.org/ver10/schema">' +
                '<Protocol>' + (options.protocol || 'RTSP') + '</Protocol>' +
                '</Transport>' +
                '</StreamSetup>' +
                '<ProfileToken>' + (options.profileToken || this.activeSource.profileToken) + '</ProfileToken>' +
                '</GetStreamUri>' +
                this._envelopeFooter()
        }, function (err, data, xml) {
            if (callback) {
                if (err) {
                    callback.call(this, err, null, xml);
                } else {
                    let mediauri = linerase(data).getStreamUriResponse.mediaUri;
                    if (mediauri.uri) {
                        let newuri = this._parseUrlKeepPort(mediauri.uri);
                        mediauri.uri = url.format(newuri);
                    }
                    callback.call(this, err, mediauri, xml);
                }
            }
        }.bind(this));
    };

and in cam.js I had

/**
 * Parse url with an eye on `preserveAddress` property but keep the port unchanged
 * @param {string} address
 * @returns {Url}
 * @private
 */
Cam.prototype._parseUrlKeepPort = function (address) {
    const parsedAddress = url.parse(address);
    // If host for service and default host differs, also if preserve address property set
    // we substitute host, hostname and port from settings
    if (this.preserveAddress && this.hostname !== parsedAddress.hostname) {
        parsedAddress.hostname = this.hostname;
        parsedAddress.host = this.hostname;
        //parsedAddress.port = this.port;
        parsedAddress.href = address;
    }
    return parsedAddress;
};
chriswiggins commented 4 years ago

I'd also suggest you add an option to keep the original port too, or allow it to be overridden? Sometimes people port-forward multiple cameras (although no one should ever put a CCTV camera on the internet!)

chriswiggins commented 3 years ago

@RogerHardiman closing this and you can send a PR if you want the functionality added?

RogerHardiman commented 3 years ago

re-opening this to remind me there is a bug I need to fix, unless there is a better bug tracker for the code

viettel-solutions commented 3 years ago

@RogerHardiman Has it work in release version yet?

viettel-solutions commented 2 years ago

Dear @RogerHardiman I wonder that what happen when the port that I forward is different from the 80 or 554