mirror of
https://github.com/taobataoma/meanTorrent.git
synced 2026-02-22 14:27:20 +01:00
feat(scrape): add UDP tracker scrape support for public CMS mode
This commit is contained in:
@@ -4,6 +4,7 @@ var path = require('path'),
|
||||
bencoding = require('bencoding'),
|
||||
common = require(path.resolve('./config/lib/common')),
|
||||
request = require('request'),
|
||||
dgram = require('dgram'),
|
||||
URL = require('url');
|
||||
|
||||
/**
|
||||
@@ -12,7 +13,6 @@ var path = require('path'),
|
||||
*/
|
||||
module.exports.doScrape = function (t, cb) {
|
||||
var scrapeInfo = [];
|
||||
|
||||
var regex = new RegExp('announce', 'g');
|
||||
console.log('torrent_announce = ' + t.torrent_announce);
|
||||
console.log('info_hash = ' + t.info_hash);
|
||||
@@ -23,6 +23,7 @@ module.exports.doScrape = function (t, cb) {
|
||||
var port = url.port;
|
||||
var path = url.pathname;
|
||||
var npath = '';
|
||||
var info_hash = escape(common.hexToBinary(t.info_hash));
|
||||
|
||||
var i = path.indexOf('announce');
|
||||
if (i >= 0) {
|
||||
@@ -39,67 +40,193 @@ module.exports.doScrape = function (t, cb) {
|
||||
scrapeUrl += port ? ':' + port : '';
|
||||
scrapeUrl += npath;
|
||||
|
||||
scrapeUrl += '?info_hash=' + escape(common.hexToBinary(t.info_hash));
|
||||
//scrapeUrl += '&info_hash=' + common.hexToBinary('5c610cb1882f13699215c8c448a2f1502e98a28e');
|
||||
scrapeUrl += '?info_hash=' + info_hash;
|
||||
console.log('-= scrape =- ' + scrapeUrl);
|
||||
|
||||
request(scrapeUrl, {encoding: null}, function (error, response, body) {
|
||||
//console.log('error:', error);
|
||||
//console.log('statusCode:', response && response.statusCode);
|
||||
//console.log('body:', body);
|
||||
if (error) {
|
||||
//console.log('-= scrape error =- ' + scrapeUrl);
|
||||
if (cb) cb(error, null);
|
||||
} else if (response) {
|
||||
if (response.statusCode === 200) {
|
||||
var data = new Buffer(body);
|
||||
var result = bencoding.decode(data);
|
||||
if (scrapeUrl.toUpperCase().startsWith('HTTP')) {
|
||||
doHTTPScrape();
|
||||
} else {
|
||||
doUDPScrape();
|
||||
}
|
||||
|
||||
//console.log(result);
|
||||
//console.log(result.toJSON());
|
||||
//console.log(result.vals[0]);
|
||||
result.keys.forEach(function (k1, idx1) {
|
||||
//console.log(k1.toString('utf8').toUpperCase() + ' - ' + idx1 + ' - ' + result.vals[idx1]);
|
||||
if (k1.toString('utf8').toUpperCase() === 'FAILURE REASON') {
|
||||
//console.log('-= scrape error =- ' + result.vals[idx1].toString('utf8'));
|
||||
if (cb) cb(result.vals[idx1].toString('utf8'), null);
|
||||
} else if (k1.toString('utf8').toUpperCase() === 'FILES') {
|
||||
var val = result.vals[idx1];
|
||||
val.keys.forEach(function (k2, idx2) {
|
||||
//console.log(k2.toString('hex'));
|
||||
//console.log(val.vals[idx2].toJSON());
|
||||
/**
|
||||
* doHTTPScrape
|
||||
*/
|
||||
function doHTTPScrape() {
|
||||
request(scrapeUrl, {encoding: null}, function (error, response, body) {
|
||||
//console.log('error:', error);
|
||||
//console.log('statusCode:', response && response.statusCode);
|
||||
//console.log('body:', body);
|
||||
if (error) {
|
||||
//console.log('-= scrape error =- ' + scrapeUrl);
|
||||
if (cb) cb(error, null);
|
||||
} else if (response) {
|
||||
if (response.statusCode === 200) {
|
||||
var data = new Buffer(body);
|
||||
var result = bencoding.decode(data);
|
||||
|
||||
scrapeInfo.push({
|
||||
info_hash: k2.toString('hex'),
|
||||
data: val.vals[idx2].toJSON()
|
||||
//console.log(result);
|
||||
//console.log(result.toJSON());
|
||||
//console.log(result.vals[0]);
|
||||
result.keys.forEach(function (k1, idx1) {
|
||||
//console.log(k1.toString('utf8').toUpperCase() + ' - ' + idx1 + ' - ' + result.vals[idx1]);
|
||||
if (k1.toString('utf8').toUpperCase() === 'FAILURE REASON') {
|
||||
//console.log('-= scrape error =- ' + result.vals[idx1].toString('utf8'));
|
||||
if (cb) cb(result.vals[idx1].toString('utf8'), null);
|
||||
} else if (k1.toString('utf8').toUpperCase() === 'FILES') {
|
||||
var val = result.vals[idx1];
|
||||
val.keys.forEach(function (k2, idx2) {
|
||||
//console.log(k2.toString('hex'));
|
||||
//console.log(val.vals[idx2].toJSON());
|
||||
|
||||
scrapeInfo.push({
|
||||
info_hash: k2.toString('hex'),
|
||||
data: val.vals[idx2].toJSON()
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
//console.log(scrapeInfo);
|
||||
if (scrapeInfo.length > 0) {
|
||||
scrapeInfo.forEach(function (s) {
|
||||
console.log(s);
|
||||
if (s.info_hash === t.info_hash) {
|
||||
t.update({
|
||||
torrent_seeds: s.data.complete,
|
||||
torrent_finished: s.data.downloaded,
|
||||
torrent_leechers: s.data.incomplete
|
||||
}).exec();
|
||||
}
|
||||
});
|
||||
if (cb) cb(null, scrapeInfo);
|
||||
} else {
|
||||
if (cb) cb('422 result is empty', null);
|
||||
//console.log(scrapeInfo);
|
||||
if (scrapeInfo.length > 0) {
|
||||
scrapeInfo.forEach(function (s) {
|
||||
console.log(s);
|
||||
if (s.info_hash === t.info_hash) {
|
||||
t.update({
|
||||
torrent_seeds: s.data.complete,
|
||||
torrent_finished: s.data.downloaded,
|
||||
torrent_leechers: s.data.incomplete
|
||||
}).exec();
|
||||
}
|
||||
});
|
||||
if (cb) cb(null, scrapeInfo);
|
||||
} else {
|
||||
if (cb) cb('422 result is empty', null);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (response.statusCode === 403) {
|
||||
if (cb) cb('403 Forbidden', null);
|
||||
}
|
||||
});
|
||||
} else if (response.statusCode === 403) {
|
||||
if (cb) cb('403 Forbidden', null);
|
||||
}
|
||||
|
||||
t.update({
|
||||
last_scrape: Date.now()
|
||||
}).exec();
|
||||
//update torrent last scrape time
|
||||
t.update({
|
||||
last_scrape: Date.now()
|
||||
}).exec();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* doUDPScrape
|
||||
*/
|
||||
function doUDPScrape() {
|
||||
var server = dgram.createSocket('udp4');
|
||||
var connectionIdHigh = 0x417;
|
||||
var connectionIdLow = 0x27101980;
|
||||
var transactionId = Math.floor((Math.random() * 100000) + 1);
|
||||
var action;
|
||||
|
||||
var ACTION_CONNECT = 0;
|
||||
var ACTION_ANNOUNCE = 1;
|
||||
var ACTION_SCRAPE = 2;
|
||||
var ACTION_ERROR = 3;
|
||||
|
||||
//server.on('listening', function () {
|
||||
// var address = server.address();
|
||||
// console.log('server listening ' + address.address + ':' + address.port);
|
||||
//});
|
||||
|
||||
server.on('message', function (msg, rinfo) {
|
||||
var buf = new Buffer(msg),
|
||||
seeders,
|
||||
completed,
|
||||
leechers;
|
||||
|
||||
//console.log(rinfo);
|
||||
action = buf.readUInt32BE(0, 4);
|
||||
transactionId = buf.readUInt32BE(4, 4);
|
||||
//console.log('returned action: ' + action);
|
||||
//console.log('returned transactionId: ' + transactionId);
|
||||
|
||||
if (action === ACTION_CONNECT) {
|
||||
//console.log('connect response');
|
||||
connectionIdHigh = buf.readUInt32BE(8, 4);
|
||||
connectionIdLow = buf.readUInt32BE(12, 4);
|
||||
scrapeTorrent();
|
||||
} else if (action === ACTION_SCRAPE) {
|
||||
//console.log('scrape response');
|
||||
var _info = {};
|
||||
_info.complete = buf.readUInt32BE(8, 4);
|
||||
_info.downloaded = buf.readUInt32BE(12, 4);
|
||||
_info.incomplete = buf.readUInt32BE(16, 4);
|
||||
|
||||
scrapeInfo.push({
|
||||
info_hash: t.info_hash,
|
||||
data: _info
|
||||
});
|
||||
//console.log(scrapeInfo);
|
||||
if (scrapeInfo.length > 0) {
|
||||
scrapeInfo.forEach(function (s) {
|
||||
console.log(s);
|
||||
if (s.info_hash === t.info_hash) {
|
||||
t.update({
|
||||
torrent_seeds: s.data.complete,
|
||||
torrent_finished: s.data.downloaded,
|
||||
torrent_leechers: s.data.incomplete
|
||||
}).exec();
|
||||
}
|
||||
});
|
||||
if (cb) cb(null, scrapeInfo);
|
||||
} else {
|
||||
if (cb) cb('422 result is empty', null);
|
||||
}
|
||||
|
||||
//update torrent last scrape time
|
||||
t.update({
|
||||
last_scrape: Date.now()
|
||||
}).exec();
|
||||
} else if (action === ACTION_ERROR) {
|
||||
//console.log('error response');
|
||||
if (cb) cb('ACTION_ERROR', null);
|
||||
}
|
||||
});
|
||||
|
||||
server.bind();
|
||||
startConnection();
|
||||
|
||||
function startConnection() {
|
||||
var buf = new Buffer(16);
|
||||
|
||||
buf.fill(0);
|
||||
|
||||
buf.writeUInt32BE(connectionIdHigh, 0);
|
||||
buf.writeUInt32BE(connectionIdLow, 4);
|
||||
buf.writeUInt32BE(ACTION_CONNECT, 8);
|
||||
buf.writeUInt32BE(transactionId, 12);
|
||||
|
||||
sendPacket(buf);
|
||||
}
|
||||
});
|
||||
|
||||
function sendPacket(buf) {
|
||||
server.send(buf, 0, buf.length, port, hostname, function (err, bytes) {
|
||||
if (err) {
|
||||
//console.log(err.message);
|
||||
if (cb) cb(err, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function scrapeTorrent() {
|
||||
var buf = new Buffer(36);
|
||||
|
||||
buf.fill(0);
|
||||
|
||||
buf.writeUInt32BE(connectionIdHigh, 0);
|
||||
buf.writeUInt32BE(connectionIdLow, 4);
|
||||
buf.writeUInt32BE(ACTION_SCRAPE, 8);
|
||||
buf.writeUInt32BE(transactionId, 12);
|
||||
buf.write(info_hash, 16, buf.length, 'hex');
|
||||
|
||||
// do scrape
|
||||
sendPacket(buf);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user