futomi / node-upnp-utils

The node-upnp-utils allows you to discover UPnP devices or services in the same subnet and to invole actions or queries to the targeted device.
MIT License
16 stars 3 forks source link

When call `stopDiscovery`, occur error of M-Search. #5

Open youkinjoh opened 7 years ago

youkinjoh commented 7 years ago

すいません。日本語で。

startDiscovery実行後、 まだM-Searchのretryが終了していないうちに stopDiscoveryをcallした場合、 エラーが発生し落ちてしまいます。

var upnpList = [];
setInterval(function() {
  var upnp = require('node-upnp-utils');
  upnp.startDiscovery();
  setTimeout(function() {
    upnp.stopDiscovery(function() {
      upnpList = upnp.getActiveDeviceList();
    });
  },5000);
}, 30000);
[proj dir]/node_modules/node-upnp-utils/lib/node-upnp-utils.js:476
    sock.send(ssdp, 0, ssdp.length, this.MULTICAST_PORT, this.MULTICAST_ADDR, (err, bytes) => {
        ^

TypeError: Cannot read property 'send' of null
    at UPnPUtils._sendMsearch ([proj dir]/node_modules/node-upnp-utils/lib/node-upnp-utils.js:476:6)
    at send ([proj dir]/node_modules/node-upnp-utils/lib/node-upnp-utils.js:345:8)
    at Timeout.msearch_timer_id.setTimeout [as _onTimeout] ([proj dir]/node_modules/node-upnp-utils/lib/node-upnp-utils.js:349:11)
    at tryOnTimeout (timers.js:228:11)
    at Timer.listOnTimeout (timers.js:202:5)
exit 1

M-Searchのretryのためにここのsendが繰り返し実行されています。 https://github.com/futomi/node-upnp-utils/blob/35fbccb1ccdea088d3ca62e174ae9f818bb22f9b/lib/node-upnp-utils.js#L344

sendの中でさらにcallしている_sendMsearchでは、 unicastを取得し次の行でsendをcallしています。 https://github.com/futomi/node-upnp-utils/blob/35fbccb1ccdea088d3ca62e174ae9f818bb22f9b/lib/node-upnp-utils.js#L475

stopDiscovery実行時には multicastunicastのcloseと削除(正確にはnullを代入)が行われています。 https://github.com/futomi/node-upnp-utils/blob/35fbccb1ccdea088d3ca62e174ae9f818bb22f9b/lib/node-upnp-utils.js#L574

この場合でも、_sendMsearchは繰り返しcallされているため、 nullとなっているunicastを取得しsendをcallしてエラーとなっています。

this.discovery_startedを見て処理にガードするのが良さそうですが、 _startMsearch内のsendで行うべきか _sendMsearch内で処理すべきか判断がつかなかったため pull requestせずにissueに登録します。

youkinjoh commented 7 years ago

多分原因がわかりました。 node.js上のtimer系の挙動が変更されているのが原因のようです。 setTimeoutsetIntervalは以前はブラウザと同じように数値を返していましたが 現在のnode.jsではTimeoutオブジェクトを返しているようです。

console.log(setTimeout(function() {}, 0).constructor); //=> [Function: Timeout]
console.log(setInterval(function() {}, 0).constructor);  //=> [Function: Timeout]