]>
git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/lib/friends.js
3 const async
= require('async')
4 const config
= require('config')
5 const fs
= require('fs')
6 const mongoose
= require('mongoose')
7 const request
= require('request')
9 const constants
= require('../initializers/constants')
10 const logger
= require('../helpers/logger')
11 const peertubeCrypto
= require('../helpers/peertubeCrypto')
12 const Pods
= require('../models/pods')
13 const requestsScheduler
= require('../lib/requestsScheduler')
14 const requests
= require('../helpers/requests')
16 const http
= config
.get('webserver.https') ? 'https' : 'http'
17 const host
= config
.get('webserver.host')
18 const port
= config
.get('webserver.port')
19 const Video
= mongoose
.model('Video')
22 addVideoToFriends: addVideoToFriends
,
23 hasFriends: hasFriends
,
24 getMyCertificate: getMyCertificate
,
25 makeFriends: makeFriends
,
26 quitFriends: quitFriends
,
27 removeVideoToFriends: removeVideoToFriends
,
28 sendOwnedVideosToPod: sendOwnedVideosToPod
31 function addVideoToFriends (video
) {
32 // ensure namePath is null
35 requestsScheduler
.addRequest('add', video
)
38 function hasFriends (callback
) {
39 Pods
.count(function (err
, count
) {
40 if (err
) return callback(err
)
42 const hasFriends
= (count
!== 0)
43 callback(null, hasFriends
)
47 function getMyCertificate (callback
) {
48 fs
.readFile(peertubeCrypto
.getCertDir() + 'peertube.pub', 'utf8', callback
)
51 function makeFriends (callback
) {
54 logger
.info('Make friends!')
55 getMyCertificate(function (err
, cert
) {
57 logger
.error('Cannot read public cert.')
61 const urls
= config
.get('network.friends')
63 async
.eachSeries(urls
, function (url
, callbackEach
) {
64 computeForeignPodsList(url
, podsScore
, callbackEach
)
66 if (err
) return callback(err
)
68 logger
.debug('Pods scores computed.', { podsScore: podsScore
})
69 const podsList
= computeWinningPods(urls
, podsScore
)
70 logger
.debug('Pods that we keep.', { podsToKeep: podsList
})
72 makeRequestsToWinningPods(cert
, podsList
, callback
)
77 function quitFriends (callback
) {
79 requestsScheduler
.deactivate()
80 // Flush pool requests
81 requestsScheduler
.flush()
84 function getPodsList (callbackAsync
) {
85 return Pods
.list(callbackAsync
)
88 function announceIQuitMyFriends (pods
, callbackAsync
) {
89 const requestParams
= {
91 path: '/api/' + constants
.API_VERSION
+ '/pods/remove',
95 // Announce we quit them
96 // We don't care if the request fails
97 // The other pod will exclude us automatically after a while
98 async
.eachLimit(pods
, constants
.REQUESTS_IN_PARALLEL
, function (pod
, callbackEach
) {
99 requestParams
.toPod
= pod
100 requests
.makeSecureRequest(requestParams
, callbackEach
)
103 logger
.error('Some errors while quitting friends.', { err: err
})
104 // Don't stop the process
107 return callbackAsync()
111 function removePodsFromDB (callbackAsync
) {
112 Pods
.removeAll(function (err
) {
113 return callbackAsync(err
)
117 function listRemoteVideos (callbackAsync
) {
118 logger
.info('Broke friends, so sad :(')
120 Video
.listRemotes(callbackAsync
)
123 function removeTheRemoteVideos (videosList
, callbackAsync
) {
124 async
.each(videosList
, function (video
, callbackEach
) {
125 video
.remove(callbackEach
)
129 // Don't forget to re activate the scheduler, even if there was an error
130 requestsScheduler
.activate()
132 if (err
) return callback(err
)
134 logger
.info('Removed all remote videos.')
135 return callback(null)
139 function removeVideoToFriends (video
) {
140 requestsScheduler
.addRequest('remove', video
)
143 function sendOwnedVideosToPod (podId
) {
144 Video
.listOwned(function (err
, videosList
) {
146 logger
.error('Cannot get the list of videos we own.')
150 videosList
.forEach(function (video
) {
151 video
.toRemoteJSON(function (err
, remoteVideo
) {
153 logger
.error('Cannot convert video to remote.', { error: err
})
154 // Don't break the process
158 requestsScheduler
.addRequestTo([ podId
], 'add', remoteVideo
)
164 // ---------------------------------------------------------------------------
166 module
.exports
= pods
168 // ---------------------------------------------------------------------------
170 function computeForeignPodsList (url
, podsScore
, callback
) {
171 getForeignPodsList(url
, function (err
, foreignPodsList
) {
172 if (err
) return callback(err
)
174 if (!foreignPodsList
) foreignPodsList
= []
176 // Let's give 1 point to the pod we ask the friends list
177 foreignPodsList
.push({ url: url
})
179 foreignPodsList
.forEach(function (foreignPod
) {
180 const foreignPodUrl
= foreignPod
.url
182 if (podsScore
[foreignPodUrl
]) podsScore
[foreignPodUrl
]++
183 else podsScore
[foreignPodUrl
] = 1
190 function computeWinningPods (urls
, podsScore
) {
191 // Build the list of pods to add
192 // Only add a pod if it exists in more than a half base pods
194 const baseScore
= urls
.length
/ 2
195 Object
.keys(podsScore
).forEach(function (pod
) {
196 if (podsScore
[pod
] > baseScore
) podsList
.push({ url: pod
})
202 function getForeignPodsList (url
, callback
) {
203 const path
= '/api/' + constants
.API_VERSION
+ '/pods'
205 request
.get(url
+ path
, function (err
, response
, body
) {
206 if (err
) return callback(err
)
208 callback(null, JSON
.parse(body
))
212 function makeRequestsToWinningPods (cert
, podsList
, callback
) {
213 // Stop pool requests
214 requestsScheduler
.deactivate()
215 // Flush pool requests
216 requestsScheduler
.forceSend()
218 async
.eachLimit(podsList
, constants
.REQUESTS_IN_PARALLEL
, function (pod
, callbackEach
) {
220 url: pod
.url
+ '/api/' + constants
.API_VERSION
+ '/pods/',
223 url: http
+ '://' + host
+ ':' + port
,
228 requests
.makeRetryRequest(params
, function (err
, res
, body
) {
230 logger
.error('Error with adding %s pod.', pod
.url
, { error: err
})
231 // Don't break the process
232 return callbackEach()
235 if (res
.statusCode
=== 200) {
236 Pods
.add({ url: pod
.url
, publicKey: body
.cert
, score: constants
.FRIEND_BASE_SCORE
}, function (err
, podCreated
) {
237 if (err
) logger
.error('Cannot add friend %s pod.', pod
.url
)
239 // Add our videos to the request scheduler
240 sendOwnedVideosToPod(podCreated
._id
)
242 return callbackEach()
245 logger
.error('Status not 200 for %s pod.', pod
.url
)
246 return callbackEach()
249 }, function endRequests () {
250 // Final callback, we've ended all the requests
251 // Now we made new friends, we can re activate the pool of requests
252 requestsScheduler
.activate()
254 logger
.debug('makeRequestsToWinningPods finished.')