;(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')
process.exit(0)
}
- checker.createDirectories()
+ checker.createDirectoriesIfNotExist()
// ----------- PeerTube modules -----------
var config = require('config')
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 -----------
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)
}
// 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)) {
;(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')
;(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')
}
// ----------- Public functions -----------
+
pods.list = function (callback) {
PodsDB.find(function (err, pods_list) {
if (err) {
}
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)
}
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 })
}
var urls = config.get('network.friends')
- var pods_score = {}
- async.each(urls, function (url, callback) {
- // Always add a trust pod
- pods_score[url] = Infinity
+ 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...')
+ makeRequestsToWinningPods(cert, pods_list)
+ })
+ })
+
+ // -----------------------------------------------------------------------
- getForeignPodsList(url, function (foreign_pods_list) {
- if (foreign_pods_list.length === 0) return callback()
+ function computeForeignPodsList (url, callback) {
+ // Always add a trust pod
+ pods_score[url] = Infinity
- 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 })
+ 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()
})
+ })
+ }
- logger.debug('Pods that we keep', { pods: pods_list })
+ 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 })
+ })
- var data = {
- url: http + '://' + host + ':' + port,
- publicKey: cert
- }
+ return pods_list
+ }
- logger.debug('Make requests...')
+ 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) {
- 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)
+ 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
;(function () {
'use strict'
- var request = require('request')
- var replay = require('request-replay')
- var ursa = require('ursa')
var config = require('config')
+ var crypto = require('crypto')
var fs = require('fs')
var openssl = require('openssl-wrapper')
- var crypto = require('crypto')
+ var request = require('request')
+ var replay = require('request-replay')
+ var ursa = require('ursa')
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) {
}
}
- 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(
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 () {}
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')
}
// 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')
})
})(crt, params, url, pod, signature)
} else {
- params.json = { data: all.data }
+ params.json = { data: all_data.data }
makeRetryRequest(params, url, pod, signature, callbackEach)
}
} else {
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)
})
})
;(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)
})
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 })
// 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',
}
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)
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) {
// 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)
}
})
}
- 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)
})
}
;(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')
}
}
- 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 = {
// 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 = {
}
}
- 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