Protocole UPnP

a marqué ce sujet comme résolu.

Salut :) ,

J'ai appris cet après midi comment marche le protocole UPnP grâce à la doc http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf et je me suis mis à créer mon code avec node.js. Mon but étant de reproduire http://miniupnp.free.fr/ pour node.js. Je compte utiliser par la suite ce code dans un projet perso notamment afin de faire du p2p

Cependant mon code actuel possède quelques problèmes:

  • Des fois la recherche SSDP est très rapide, puis au bout de quelques minutes j'ai beau relancer le code je ne reçois plus de message de réponse, c'est à dire:
1
2
3
4
5
6
7
HTTP/1.1 200 OK
Cache-Control: max-age=1900
Location: http://192.168.0.1:80/RootDevice.xml
Server: UPnP/1.0 UPnP/1.0 UPnP-Device-Host/1.0
ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1
USN: uuid:upnp-InternetGatewayDevice-1_0-7cb733b78a5f::urn:schemas-upnp-org:device:InternetGatewayDevice:1
EXT:
  • J'ai un problème au niveau de la req HTTP –> getSOAPResponse() –> J'ai Error: read ECONNRESET.

Voici le code, je vous laisse le tester: ( cela requiert juste npm install ip et npm install http)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
// Basé sur http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
var dgram  = require('dgram'),
    url     = require('url'),
    myIp   = require('ip').address(),
    http  = require('http'),
    myPort = 8080,
    socket = dgram.createSocket('udp4');

// constantes - ne pas changer
const SSDP_HOST = '239.255.255.250';
const SSDP_PORT = '1900';
const SSDP_TARGET  = 'urn:schemas-upnp-org:device:InternetGatewayDevice:1';
const SOAP_ENV_PRE = '<?xml version="1.0"?>\n<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">\n<s:Body>\n';
const SOAP_ENV_POST = '</s:Body>\n</s:Envelope>\n';
const WANIP = "urn:schemas-upnp-org:service:WANIPConnection:1";
var info;

// ssdp search
function broadcastSsdp() {
  console.log('Searching...');

  var search = new Buffer([
      'M-SEARCH * HTTP/1.1',
      'HOST: ' + SSDP_HOST + ':' + SSDP_PORT,
      'MAN: "ssdp:discover"',
      'MX: 3',
      'ST: ' + SSDP_TARGET + ''
  ].join('\r\n'));

  socket.send(search, 0, search.length, SSDP_PORT, SSDP_HOST);
}

function getSOAPResponse(soap, func, callback) {
  var xml = [SOAP_ENV_PRE, soap, SOAP_ENV_POST].join("");

  var options =  {  
    host: info.hostname,
    method: 'POST',
    headers: {
      'Content-Length': xml.length, 
      'Content-Type': 'text/xml',
      'SOAPAction': '"' + WANIP + '#' + func + '"'
    }
  };

  http.request(options, function (error, response, body) {
      if (error) {
          return console.error('error:', error);
      }

      if (response.headers['content-length']) {
          console.log("Got response: " + res.statusCode);
      }
  });

}

function getExternalIP(callback) {
  console.log('getExternalIP...');
  var xml = '<u:GetExternalIPAddress xmlns:u="' + WANIP + '"></u:GetExternalIPAddress>\n';

  getSOAPResponse(xml, "GetExternalIPAddress", function(err, xml) {
    if (err) callback(err);
    else callback(null, xml.match(/<NewExternalIPAddress>(.+?)<\/NewExternalIPAddress>/i)[1]);
  });
}

function addPortMapping(protocol, extPort, intPort, host, description, callback) {
  console.log('addPortMapping...');
  var xml =
  '<u:AddPortMapping xmlns:u="' + WANIP + '">\n' +
    '<NewRemoteHost></NewRemoteHost>\n' +
    '<NewExternalPort>' + extPort + '</NewExternalPort>\n' +
    '<NewProtocol>' + protocol + '</NewProtocol>\n' +
    '<NewInternalPort>' + intPort + '</NewInternalPort>\n' +
    '<NewInternalClient>' + host + '</NewInternalClient>\n' +
    '<NewEnabled>1</NewEnabled>\n' +
    '<NewPortMappingDescription>' + description + '</NewPortMappingDescription>\n' +
    '<NewLeaseDuration>0</NewLeaseDuration>\n' +
  '</u:AddPortMapping>';

  getSOAPResponse(xml, "AddPortMapping", callback);
}

socket.on('listening', function () {
  console.log('socket ready...');
  broadcastSsdp();
});

socket.on('message', function (chunk) {
  var message = chunk.toString();
  console.log(message);
  info = url.parse(message.match(/location:(.+?)\r\n/i)[1].trim());
  getExternalIP();
  addPortMapping("TCP", 8888, 8888, myIp, "My cool app", function(err) {
        if (err) throw err;
        console.log("Success");
        console.log("Done.");
    });
});

console.log('binding to', myIp + ':' + myPort);
socket.bind(myPort, myIp);
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte