]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/assets/player/p2p-media-loader/segment-validator.ts
Fix muted accounts on overviews
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / p2p-media-loader / segment-validator.ts
CommitLineData
09209296
C
1import { Segment } from 'p2p-media-loader-core'
2import { basename } from 'path'
3
c6c0fa6c
C
4type SegmentsJSON = { [filename: string]: string | { [byterange: string]: string } }
5
09209296 6function segmentValidatorFactory (segmentsSha256Url: string) {
c6c0fa6c 7 let segmentsJSON = fetchSha256Segments(segmentsSha256Url)
4c280004 8 const regex = /bytes=(\d+)-(\d+)/
09209296 9
c6c0fa6c 10 return async function segmentValidator (segment: Segment, canRefetchSegmentHashes = true) {
4c280004 11 const filename = basename(segment.url)
09209296 12
c6c0fa6c
C
13 const segmentValue = (await segmentsJSON)[filename]
14
15 if (!segmentValue && !canRefetchSegmentHashes) {
16 throw new Error(`Unknown segment name ${filename} in segment validator`)
17 }
18
19 if (!segmentValue) {
20 console.log('Refetching sha segments.')
21
22 // Refetch
23 segmentsJSON = fetchSha256Segments(segmentsSha256Url)
24 segmentValidator(segment, false)
25 return
26 }
27
28 let hashShouldBe: string
29 let range = ''
30
31 if (typeof segmentValue === 'string') {
32 hashShouldBe = segmentValue
33 } else {
34 const captured = regex.exec(segment.range)
35 range = captured[1] + '-' + captured[2]
36
37 hashShouldBe = segmentValue[range]
38 }
4c280004 39
09209296 40 if (hashShouldBe === undefined) {
4c280004 41 throw new Error(`Unknown segment name ${filename}/${range} in segment validator`)
09209296
C
42 }
43
6d61da4e 44 const calculatedSha = await sha256Hex(segment.data)
09209296 45 if (calculatedSha !== hashShouldBe) {
4c280004
C
46 throw new Error(
47 `Hashes does not correspond for segment ${filename}/${range}` +
48 `(expected: ${hashShouldBe} instead of ${calculatedSha})`
49 )
09209296
C
50 }
51 }
52}
53
54// ---------------------------------------------------------------------------
55
56export {
57 segmentValidatorFactory
58}
59
60// ---------------------------------------------------------------------------
61
62function fetchSha256Segments (url: string) {
63 return fetch(url)
c6c0fa6c 64 .then(res => res.json() as Promise<SegmentsJSON>)
09209296
C
65 .catch(err => {
66 console.error('Cannot get sha256 segments', err)
67 return {}
68 })
69}
70
6d61da4e 71async function sha256Hex (data?: ArrayBuffer) {
09209296
C
72 if (!data) return undefined
73
6d61da4e
C
74 if (window.crypto.subtle) {
75 return window.crypto.subtle.digest('SHA-256', data)
76 .then(data => bufferToHex(data))
77 }
78
79 // Fallback for non HTTPS context
80 const shaModule = await import('sha.js')
81 return new shaModule.sha256().update(Buffer.from(data)).digest('hex')
09209296
C
82}
83
84// Thanks: https://stackoverflow.com/a/53307879
6d61da4e 85function bufferToHex (buffer?: ArrayBuffer) {
09209296
C
86 if (!buffer) return ''
87
88 let s = ''
89 const h = '0123456789abcdef'
90 const o = new Uint8Array(buffer)
91
92 o.forEach((v: any) => s += h[ v >> 4 ] + h[ v & 15 ])
93
94 return s
95}