diff --git a/server/controllers/tracker.ts b/server/controllers/tracker.ts index 42f5aea81..9bc7586d1 100644 --- a/server/controllers/tracker.ts +++ b/server/controllers/tracker.ts @@ -5,6 +5,7 @@ import * as bitTorrentTracker from 'bittorrent-tracker' import * as proxyAddr from 'proxy-addr' import { Server as WebSocketServer } from 'ws' import { CONFIG, TRACKER_RATE_LIMITS } from '../initializers/constants' +import { VideoFileModel } from '../models/video/video-file' const TrackerServer = bitTorrentTracker.Server @@ -37,7 +38,12 @@ const trackerServer = new TrackerServer({ return cb(new Error(`Too many requests (${peersIpInfoHash[ key ]} of ip ${ip} for torrent ${infoHash}`)) } - return cb() + VideoFileModel.isInfohashExists(infoHash) + .then(exists => { + if (exists === false) return cb(new Error(`Unknown infoHash ${infoHash}`)) + + return cb() + }) } }) diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts index f5a2b6c1f..3bc4855f3 100644 --- a/server/models/video/video-file.ts +++ b/server/models/video/video-file.ts @@ -9,6 +9,7 @@ import { import { CONSTRAINTS_FIELDS } from '../../initializers' import { throwIfNotValid } from '../utils' import { VideoModel } from './video' +import * as Sequelize from 'sequelize' @Table({ tableName: 'videoFile', @@ -68,4 +69,18 @@ export class VideoFileModel extends Model { onDelete: 'CASCADE' }) Video: VideoModel + + static isInfohashExists (infoHash: string) { + const query = 'SELECT 1 FROM "videoFile" WHERE "infoHash" = $infoHash LIMIT 1' + const options = { + type: Sequelize.QueryTypes.SELECT, + bind: { infoHash }, + raw: true + } + + return VideoModel.sequelize.query(query, options) + .then(results => { + return results.length === 1 + }) + } } diff --git a/server/tests/api/index-fast.ts b/server/tests/api/index-fast.ts index 531a09b82..02ffdd4f1 100644 --- a/server/tests/api/index-fast.ts +++ b/server/tests/api/index-fast.ts @@ -15,3 +15,4 @@ import './server/email' import './server/config' import './server/reverse-proxy' import './search/search-videos' +import './server/tracker' diff --git a/server/tests/api/server/tracker.ts b/server/tests/api/server/tracker.ts new file mode 100644 index 000000000..5d61c1558 --- /dev/null +++ b/server/tests/api/server/tracker.ts @@ -0,0 +1,71 @@ +/* tslint:disable:no-unused-expression */ + +import * as magnetUtil from 'magnet-uri' +import * as chai from 'chai' +import 'mocha' +import { getVideo, killallServers, runServer, ServerInfo, uploadVideo } from '../../utils' +import { flushTests, setAccessTokensToServers } from '../../utils/index' +import { VideoDetails } from '../../../../shared/models/videos' +import * as WebTorrent from 'webtorrent' + +describe('Test tracker', function () { + let server: ServerInfo + let badMagnet: string + let goodMagnet: string + + before(async function () { + this.timeout(60000) + + await flushTests() + server = await runServer(1) + await setAccessTokensToServers([ server ]) + + { + const res = await uploadVideo(server.url, server.accessToken, {}) + const videoUUID = res.body.video.uuid + + const resGet = await getVideo(server.url, videoUUID) + const video: VideoDetails = resGet.body + goodMagnet = video.files[0].magnetUri + + const parsed = magnetUtil.decode(goodMagnet) + parsed.infoHash = '010597bb88b1968a5693a4fa8267c592ca65f2e9' + + badMagnet = magnetUtil.encode(parsed) + } + }) + + it('Should return an error when adding an incorrect infohash', done => { + this.timeout(10000) + const webtorrent = new WebTorrent() + + const torrent = webtorrent.add(badMagnet) + + torrent.on('error', done) + torrent.on('warning', warn => { + const message = typeof warn === 'string' ? warn : warn.message + if (message.indexOf('Unknown infoHash ') !== -1) return done() + }) + + torrent.on('done', () => done(new Error('No error on infohash'))) + }) + + it('Should succeed with the correct infohash', done => { + this.timeout(10000) + const webtorrent = new WebTorrent() + + const torrent = webtorrent.add(goodMagnet) + + torrent.on('error', done) + torrent.on('warning', warn => { + const message = typeof warn === 'string' ? warn : warn.message + if (message.indexOf('Unknown infoHash ') !== -1) return done(new Error('Error on infohash')) + }) + + torrent.on('done', done) + }) + + after(async function () { + killallServers([ server ]) + }) +})