mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-11-25 18:20:31 -06:00
Source refractoring
This commit is contained in:
parent
16357143ae
commit
a18603803a
22
server.js
22
server.js
@ -1,20 +1,22 @@
|
||||
;(function () {
|
||||
'use strict'
|
||||
|
||||
// ----------- Constantes -----------
|
||||
// ----------- Constants -----------
|
||||
global.API_VERSION = 'v1'
|
||||
|
||||
// ----------- Node modules -----------
|
||||
var bodyParser = require('body-parser')
|
||||
var express = require('express')
|
||||
var expressValidator = require('express-validator')
|
||||
var path = require('path')
|
||||
var http = require('http')
|
||||
var morgan = require('morgan')
|
||||
var bodyParser = require('body-parser')
|
||||
var multer = require('multer')
|
||||
var path = require('path')
|
||||
var TrackerServer = require('bittorrent-tracker').Server
|
||||
var WebSocketServer = require('ws').Server
|
||||
|
||||
// Create our main app
|
||||
var app = express()
|
||||
var http = require('http')
|
||||
|
||||
// ----------- Checker -----------
|
||||
var checker = require('./src/checker')
|
||||
@ -26,7 +28,7 @@
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
checker.createDirectories()
|
||||
checker.createDirectoriesIfNotExist()
|
||||
|
||||
// ----------- PeerTube modules -----------
|
||||
var config = require('config')
|
||||
@ -36,16 +38,22 @@
|
||||
var videos = require('./src/videos')
|
||||
var webtorrent = require('./src/webTorrentNode')
|
||||
|
||||
// Get configurations
|
||||
var port = config.get('listen.port')
|
||||
var uploads = config.get('storage.uploads')
|
||||
|
||||
// ----------- Command line -----------
|
||||
|
||||
// ----------- App -----------
|
||||
|
||||
// For the logger
|
||||
app.use(morgan('combined', { stream: logger.stream }))
|
||||
// For body requests
|
||||
app.use(bodyParser.json())
|
||||
// For POST file requests
|
||||
app.use(multer({ dest: uploads }))
|
||||
app.use(bodyParser.urlencoded({ extended: false }))
|
||||
// Validate some params for the API
|
||||
app.use(expressValidator())
|
||||
|
||||
// ----------- Views, routes and static files -----------
|
||||
@ -55,15 +63,17 @@
|
||||
port: 35729
|
||||
}))
|
||||
|
||||
// Catch sefaults
|
||||
require('segfault-handler').registerHandler()
|
||||
|
||||
// Static files
|
||||
app.use(express.static(path.join(__dirname, '/public'), { maxAge: 0 }))
|
||||
|
||||
// Jade template from ./views directory
|
||||
app.set('views', path.join(__dirname, '/views'))
|
||||
app.set('view engine', 'jade')
|
||||
|
||||
// API
|
||||
// API routes
|
||||
var api_route = '/api/' + global.API_VERSION
|
||||
app.use(api_route, routes.api)
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
}
|
||||
|
||||
// Create directories for the storage if it doesn't exist
|
||||
checker.createDirectories = function () {
|
||||
checker.createDirectoriesIfNotExist = function () {
|
||||
var storages = config.get('storage')
|
||||
|
||||
for (var key of Object.keys(storages)) {
|
||||
|
@ -1,10 +1,9 @@
|
||||
;(function () {
|
||||
// Thanks http://tostring.it/2014/06/23/advanced-logging-with-nodejs/
|
||||
|
||||
'use strict'
|
||||
|
||||
var winston = require('winston')
|
||||
var config = require('config')
|
||||
var winston = require('winston')
|
||||
|
||||
var logDir = __dirname + '/../' + config.get('storage.logs')
|
||||
|
||||
|
162
src/pods.js
162
src/pods.js
@ -1,16 +1,17 @@
|
||||
;(function () {
|
||||
'use strict'
|
||||
|
||||
var fs = require('fs')
|
||||
var config = require('config')
|
||||
var async = require('async')
|
||||
var config = require('config')
|
||||
var fs = require('fs')
|
||||
var request = require('request')
|
||||
|
||||
var logger = require('./logger')
|
||||
var utils = require('./utils')
|
||||
var PodsDB = require('./database').PodsDB
|
||||
var utils = require('./utils')
|
||||
|
||||
var pods = {}
|
||||
|
||||
var http = config.get('webserver.https') ? 'https' : 'http'
|
||||
var host = config.get('webserver.host')
|
||||
var port = config.get('webserver.port')
|
||||
@ -27,6 +28,7 @@
|
||||
}
|
||||
|
||||
// ----------- Public functions -----------
|
||||
|
||||
pods.list = function (callback) {
|
||||
PodsDB.find(function (err, pods_list) {
|
||||
if (err) {
|
||||
@ -73,18 +75,27 @@
|
||||
}
|
||||
|
||||
logger.debug('Make multiple requests.')
|
||||
|
||||
var params = {
|
||||
encrypt: true,
|
||||
sign: true,
|
||||
method: data.method,
|
||||
path: data.path,
|
||||
data: data.data
|
||||
}
|
||||
|
||||
utils.makeMultipleRetryRequest(
|
||||
{ encrypt: true, sign: true, method: data.method, path: data.path, data: data.data },
|
||||
params,
|
||||
|
||||
urls,
|
||||
|
||||
function (err, response, body, url) {
|
||||
function callbackEachPodFinished (err, response, body, url) {
|
||||
if (err || response.statusCode !== 200) {
|
||||
logger.error('Error sending secure request to %s/%s pod.', url, data.path, { error: err })
|
||||
}
|
||||
},
|
||||
|
||||
function (err) {
|
||||
function callbackAllPodsFinished (err) {
|
||||
if (err) {
|
||||
logger.error('There was some errors when sending the video meta data.', { error: err })
|
||||
return callback(err)
|
||||
@ -98,7 +109,9 @@
|
||||
}
|
||||
|
||||
pods.makeFriends = function (callback) {
|
||||
logger.debug('Read public key...')
|
||||
var pods_score = {}
|
||||
|
||||
logger.info('Make friends!')
|
||||
fs.readFile(utils.certDir + 'peertube.pub', 'utf8', function (err, cert) {
|
||||
if (err) {
|
||||
logger.error('Cannot read public cert.', { error: err })
|
||||
@ -106,71 +119,86 @@
|
||||
}
|
||||
|
||||
var urls = config.get('network.friends')
|
||||
var pods_score = {}
|
||||
|
||||
async.each(urls, function (url, callback) {
|
||||
// Always add a trust pod
|
||||
pods_score[url] = Infinity
|
||||
|
||||
getForeignPodsList(url, function (foreign_pods_list) {
|
||||
if (foreign_pods_list.length === 0) return callback()
|
||||
|
||||
async.each(foreign_pods_list, function (foreign_pod, callback) {
|
||||
var foreign_url = foreign_pod.url
|
||||
if (pods_score[foreign_url]) pods_score[foreign_url]++
|
||||
else pods_score[foreign_url] = 1
|
||||
callback()
|
||||
}, callback)
|
||||
})
|
||||
}, function () {
|
||||
logger.debug('Pods score', { pods_score: pods_score })
|
||||
|
||||
// Build the list of pods to add
|
||||
// Only add a pod if it exists in more than a half base pods
|
||||
var pods_list = []
|
||||
var base_score = urls.length / 2
|
||||
Object.keys(pods_score).forEach(function (pod) {
|
||||
if (pods_score[pod] > base_score) pods_list.push({ url: pod })
|
||||
})
|
||||
|
||||
logger.debug('Pods that we keep', { pods: pods_list })
|
||||
|
||||
var data = {
|
||||
url: http + '://' + host + ':' + port,
|
||||
publicKey: cert
|
||||
}
|
||||
async.each(urls, computeForeignPodsList, function () {
|
||||
logger.debug('Pods scores computed.', { pods_score: pods_score })
|
||||
var pods_list = computeWinningPods(urls, pods_score)
|
||||
logger.debug('Pods that we keep computed.', { pods_to_keep: pods_list })
|
||||
|
||||
logger.debug('Make requests...')
|
||||
|
||||
utils.makeMultipleRetryRequest(
|
||||
{ method: 'POST', path: '/api/' + global.API_VERSION + '/pods/', data: data },
|
||||
|
||||
pods_list,
|
||||
|
||||
function eachRequest (err, response, body, url) {
|
||||
if (!err && response.statusCode === 200) {
|
||||
pods.add({ url: url, publicKey: body.cert }, function (err) {
|
||||
if (err) {
|
||||
logger.error('Error with adding %s pod.', url, { error: err })
|
||||
}
|
||||
})
|
||||
} else {
|
||||
logger.error('Error with adding %s pod.', url)
|
||||
}
|
||||
},
|
||||
|
||||
function endRequests (err) {
|
||||
if (err) {
|
||||
logger.error('There was some errors when we wanted to make friends.', { error: err })
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
logger.debug('Finished')
|
||||
callback(null)
|
||||
}
|
||||
)
|
||||
makeRequestsToWinningPods(cert, pods_list)
|
||||
})
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
function computeForeignPodsList (url, callback) {
|
||||
// Always add a trust pod
|
||||
pods_score[url] = Infinity
|
||||
|
||||
getForeignPodsList(url, function (foreign_pods_list) {
|
||||
if (foreign_pods_list.length === 0) return callback()
|
||||
|
||||
async.each(foreign_pods_list, function (foreign_pod, callback_each) {
|
||||
var foreign_url = foreign_pod.url
|
||||
|
||||
if (pods_score[foreign_url]) pods_score[foreign_url]++
|
||||
else pods_score[foreign_url] = 1
|
||||
|
||||
callback_each()
|
||||
}, function () {
|
||||
callback()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function computeWinningPods (urls, pods_score) {
|
||||
// Build the list of pods to add
|
||||
// Only add a pod if it exists in more than a half base pods
|
||||
var pods_list = []
|
||||
var base_score = urls.length / 2
|
||||
Object.keys(pods_score).forEach(function (pod) {
|
||||
if (pods_score[pod] > base_score) pods_list.push({ url: pod })
|
||||
})
|
||||
|
||||
return pods_list
|
||||
}
|
||||
|
||||
function makeRequestsToWinningPods (cert, pods_list) {
|
||||
var data = {
|
||||
url: http + '://' + host + ':' + port,
|
||||
publicKey: cert
|
||||
}
|
||||
|
||||
utils.makeMultipleRetryRequest(
|
||||
{ method: 'POST', path: '/api/' + global.API_VERSION + '/pods/', data: data },
|
||||
|
||||
pods_list,
|
||||
|
||||
function eachRequest (err, response, body, url) {
|
||||
// We add the pod if it responded correctly with its public certificate
|
||||
if (!err && response.statusCode === 200) {
|
||||
pods.add({ url: url, publicKey: body.cert }, function (err) {
|
||||
if (err) {
|
||||
logger.error('Error with adding %s pod.', url, { error: err })
|
||||
}
|
||||
})
|
||||
} else {
|
||||
logger.error('Error with adding %s pod.', url, { error: err || new Error('Status not 200') })
|
||||
}
|
||||
},
|
||||
|
||||
function endRequests (err) {
|
||||
if (err) {
|
||||
logger.error('There was some errors when we wanted to make friends.', { error: err })
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
logger.debug('makeRequestsToWinningPods finished.')
|
||||
return callback(null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = pods
|
||||
|
39
src/utils.js
39
src/utils.js
@ -1,23 +1,23 @@
|
||||
;(function () {
|
||||
'use strict'
|
||||
|
||||
var config = require('config')
|
||||
var crypto = require('crypto')
|
||||
var fs = require('fs')
|
||||
var openssl = require('openssl-wrapper')
|
||||
var request = require('request')
|
||||
var replay = require('request-replay')
|
||||
var ursa = require('ursa')
|
||||
var config = require('config')
|
||||
var fs = require('fs')
|
||||
var openssl = require('openssl-wrapper')
|
||||
var crypto = require('crypto')
|
||||
|
||||
var logger = require('./logger')
|
||||
|
||||
var utils = {}
|
||||
|
||||
var http = config.get('webserver.https') ? 'https' : 'http'
|
||||
var host = config.get('webserver.host')
|
||||
var port = config.get('webserver.port')
|
||||
var algorithm = 'aes-256-ctr'
|
||||
|
||||
var utils = {}
|
||||
|
||||
// ----------- Private functions ----------
|
||||
|
||||
function makeRetryRequest (params, from_url, to_pod, signature, callbackEach) {
|
||||
@ -29,7 +29,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug('Sending informations to %s', to_pod.url, { params: params })
|
||||
logger.debug('Sending informations to %s.', to_pod.url, { params: params })
|
||||
|
||||
// Replay 15 times, with factor 3
|
||||
replay(
|
||||
@ -52,7 +52,7 @@
|
||||
utils.certDir = __dirname + '/../' + config.get('storage.certs')
|
||||
|
||||
// { path, data }
|
||||
utils.makeMultipleRetryRequest = function (all, pods, callbackEach, callback) {
|
||||
utils.makeMultipleRetryRequest = function (all_data, pods, callbackEach, callback) {
|
||||
if (!callback) {
|
||||
callback = callbackEach
|
||||
callbackEach = function () {}
|
||||
@ -61,8 +61,8 @@
|
||||
var url = http + '://' + host + ':' + port
|
||||
var signature
|
||||
|
||||
// Signature ?
|
||||
if (all.method === 'POST' && all.data && all.sign === true) {
|
||||
// Add signature if it is specified in the params
|
||||
if (all_data.method === 'POST' && all_data.data && all_data.sign === true) {
|
||||
var myKey = ursa.createPrivateKey(fs.readFileSync(utils.certDir + 'peertube.key.pem'))
|
||||
signature = myKey.hashAndSign('sha256', url, 'utf8', 'hex')
|
||||
}
|
||||
@ -70,22 +70,21 @@
|
||||
// Make a request for each pod
|
||||
for (var pod of pods) {
|
||||
var params = {
|
||||
url: pod.url + all.path,
|
||||
method: all.method
|
||||
url: pod.url + all_data.path,
|
||||
method: all_data.method
|
||||
}
|
||||
|
||||
// Add data with POST requst ?
|
||||
if (all.method === 'POST' && all.data) {
|
||||
if (all_data.method === 'POST' && all_data.data) {
|
||||
logger.debug('Make a POST request.')
|
||||
|
||||
// Encrypt data ?
|
||||
if (all.encrypt === true) {
|
||||
logger.debug(pod.publicKey)
|
||||
if (all_data.encrypt === true) {
|
||||
var crt = ursa.createPublicKey(pod.publicKey)
|
||||
|
||||
// TODO: ES6 with let
|
||||
;(function (crt_copy, copy_params, copy_url, copy_pod, copy_signature) {
|
||||
utils.symetricEncrypt(JSON.stringify(all.data), function (err, dataEncrypted) {
|
||||
utils.symetricEncrypt(JSON.stringify(all_data.data), function (err, dataEncrypted) {
|
||||
if (err) throw err
|
||||
|
||||
var passwordEncrypted = crt_copy.encrypt(dataEncrypted.password, 'utf8', 'hex')
|
||||
@ -98,7 +97,7 @@
|
||||
})
|
||||
})(crt, params, url, pod, signature)
|
||||
} else {
|
||||
params.json = { data: all.data }
|
||||
params.json = { data: all_data.data }
|
||||
makeRetryRequest(params, url, pod, signature, callbackEach)
|
||||
}
|
||||
} else {
|
||||
@ -124,20 +123,22 @@
|
||||
return callback(new Error(string))
|
||||
}
|
||||
|
||||
logger.debug('Gen RSA keys...')
|
||||
logger.info('Generating a RSA key...')
|
||||
openssl.exec('genrsa', { 'out': utils.certDir + 'peertube.key.pem', '2048': false }, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot create private key on this pod.', { error: err })
|
||||
return callback(err)
|
||||
}
|
||||
logger.info('RSA key generated.')
|
||||
|
||||
logger.debug('Manage public key...')
|
||||
logger.info('Manage public key...')
|
||||
openssl.exec('rsa', { 'in': utils.certDir + 'peertube.key.pem', 'pubout': true, 'out': utils.certDir + 'peertube.pub' }, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot create public key on this pod .', { error: err })
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
logger.info('Public key managed.')
|
||||
return callback(null)
|
||||
})
|
||||
})
|
||||
|
@ -1,27 +1,27 @@
|
||||
;(function () {
|
||||
'use strict'
|
||||
|
||||
var async = require('async')
|
||||
var config = require('config')
|
||||
var fs = require('fs')
|
||||
var webtorrent = require('./webTorrentNode')
|
||||
var config = require('config')
|
||||
var async = require('async')
|
||||
|
||||
var logger = require('./logger')
|
||||
var VideosDB = require('./database').VideosDB
|
||||
var pods = require('./pods')
|
||||
var VideosDB = require('./database').VideosDB
|
||||
|
||||
var videos = {}
|
||||
// Public url
|
||||
|
||||
var http = config.get('webserver.https') === true ? 'https' : 'http'
|
||||
var host = config.get('webserver.host')
|
||||
var port = config.get('webserver.port')
|
||||
|
||||
// ----------- Private functions -----------
|
||||
function seedVideo (path, callback) {
|
||||
logger.debug('Seeding : %s', path)
|
||||
logger.info('Seeding %s...', path)
|
||||
|
||||
webtorrent.seed(path, function (torrent) {
|
||||
logger.debug('Seeded : %s', torrent.magnetURI)
|
||||
logger.info('%s seeded (%s).', path, torrent.magnetURI)
|
||||
|
||||
return callback(null, torrent)
|
||||
})
|
||||
@ -46,7 +46,7 @@
|
||||
var video_file = data.video
|
||||
var video_data = data.data
|
||||
|
||||
logger.debug('Path: %s', video_file.path)
|
||||
logger.info('Adding %s video.', video_file.path)
|
||||
seedVideo(video_file.path, function (err, torrent) {
|
||||
if (err) {
|
||||
logger.error('Cannot seed this video.', { error: err })
|
||||
@ -70,7 +70,7 @@
|
||||
// Now we'll send the video's meta data
|
||||
params.namePath = null
|
||||
|
||||
logger.debug('Sending this video Uri to friends...')
|
||||
logger.info('Sending %s video to friends.', video_file.path)
|
||||
|
||||
var data = {
|
||||
path: '/api/' + global.API_VERSION + '/remotevideos/add',
|
||||
@ -91,7 +91,7 @@
|
||||
}
|
||||
|
||||
videos.remove = function (id, callback) {
|
||||
// Maybe the torrent is not seeding, it doesn't have importance
|
||||
// Maybe the torrent is not seeded, but we catch the error to don't stop the removing process
|
||||
function removeTorrent (magnetUri, callback) {
|
||||
try {
|
||||
webtorrent.remove(magnetUri, callback)
|
||||
@ -114,7 +114,7 @@
|
||||
return callback(new Error(error_string))
|
||||
}
|
||||
|
||||
logger.debug('Removing video %s', video.magnetUri)
|
||||
logger.info('Removing %s video', video.name)
|
||||
|
||||
removeTorrent(video.magnetUri, function () {
|
||||
VideosDB.findByIdAndRemove(id, function (err) {
|
||||
@ -154,16 +154,15 @@
|
||||
|
||||
// Use the magnet Uri because the _id field is not the same on different servers
|
||||
videos.removeRemote = function (fromUrl, magnetUri, callback) {
|
||||
// TODO : check if the remote server has the rights to remove this video
|
||||
|
||||
VideosDB.findOne({ magnetUri: magnetUri }, function (err, video) {
|
||||
if (err || !video) {
|
||||
logger.error('Cannot find the torrent URI of this remote video.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
// TODO: move to reqValidators middleware ?
|
||||
if (video.podUrl !== fromUrl) {
|
||||
logger.error('The pod has not rights on this video.')
|
||||
logger.error('The pod has not the rights on this video.')
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
@ -222,23 +221,23 @@
|
||||
})
|
||||
}
|
||||
|
||||
videos.seedAll = function (final_callback) {
|
||||
videos.seedAll = function (callback) {
|
||||
VideosDB.find({ namePath: { $ne: null } }, function (err, videos_list) {
|
||||
if (err) {
|
||||
logger.error('Cannot get list of the videos to seed.', { error: err })
|
||||
return final_callback(err)
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
async.each(videos_list, function (video, callback) {
|
||||
async.each(videos_list, function (video, each_callback) {
|
||||
seedVideo(videos.uploadDir + video.namePath, function (err) {
|
||||
if (err) {
|
||||
logger.error('Cannot seed this video.', { error: err })
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null)
|
||||
each_callback(null)
|
||||
})
|
||||
}, final_callback)
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
;(function () {
|
||||
'use strict'
|
||||
|
||||
var spawn = require('electron-spawn')
|
||||
var config = require('config')
|
||||
var ipc = require('node-ipc')
|
||||
var pathUtils = require('path')
|
||||
var spawn = require('electron-spawn')
|
||||
|
||||
var logger = require('./logger')
|
||||
|
||||
@ -85,12 +85,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (!webtorrentnode.silent) logger.debug('Node wants to seed ' + data._id)
|
||||
if (!webtorrentnode.silent) logger.debug('Node wants to seed %s.', data._id)
|
||||
|
||||
// Finish signal
|
||||
var event_key = nodeKey + '.seedDone.' + data._id
|
||||
ipc.server.on(event_key, function listener (received) {
|
||||
if (!webtorrentnode.silent) logger.debug('Process seeded torrent ' + received.magnetUri)
|
||||
if (!webtorrentnode.silent) logger.debug('Process seeded torrent %s.', received.magnetUri)
|
||||
|
||||
// This is a fake object, we just use the magnetUri in this project
|
||||
var torrent = {
|
||||
@ -117,7 +117,7 @@
|
||||
// Finish signal
|
||||
var event_key = nodeKey + '.addDone.' + data._id
|
||||
ipc.server.on(event_key, function (received) {
|
||||
if (!webtorrentnode.silent) logger.debug('Process added torrent')
|
||||
if (!webtorrentnode.silent) logger.debug('Process added torrent.')
|
||||
|
||||
// This is a fake object, we just use the magnetUri in this project
|
||||
var torrent = {
|
||||
@ -139,12 +139,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (!webtorrentnode.silent) logger.debug('Node wants to stop seeding ' + data._id)
|
||||
if (!webtorrentnode.silent) logger.debug('Node wants to stop seeding %s.', data._id)
|
||||
|
||||
// Finish signal
|
||||
var event_key = nodeKey + '.removeDone.' + data._id
|
||||
ipc.server.on(event_key, function (received) {
|
||||
if (!webtorrentnode.silent) logger.debug('Process removed torrent ' + data._id)
|
||||
if (!webtorrentnode.silent) logger.debug('Process removed torrent %s.', data._id)
|
||||
|
||||
var err = null
|
||||
if (received.err) err = received.err
|
||||
|
Loading…
Reference in New Issue
Block a user