1 import { Segment } from 'p2p-media-loader-core'
2 import { basename } from 'path'
4 type SegmentsJSON = { [filename: string]: string | { [byterange: string]: string } }
6 function segmentValidatorFactory (segmentsSha256Url: string) {
7 let segmentsJSON = fetchSha256Segments(segmentsSha256Url)
8 const regex = /bytes=(\d+)-(\d+)/
10 return async function segmentValidator (segment: Segment, canRefetchSegmentHashes = true) {
11 const filename = basename(segment.url)
13 const segmentValue = (await segmentsJSON)[filename]
15 if (!segmentValue && !canRefetchSegmentHashes) {
16 throw new Error(`Unknown segment name ${filename} in segment validator`)
20 console.log('Refetching sha segments.')
23 segmentsJSON = fetchSha256Segments(segmentsSha256Url)
24 segmentValidator(segment, false)
28 let hashShouldBe: string
31 if (typeof segmentValue === 'string') {
32 hashShouldBe = segmentValue
34 const captured = regex.exec(segment.range)
35 range = captured[1] + '-' + captured[2]
37 hashShouldBe = segmentValue[range]
40 if (hashShouldBe === undefined) {
41 throw new Error(`Unknown segment name ${filename}/${range} in segment validator`)
44 const calculatedSha = bufferToEx(await sha256(segment.data))
45 if (calculatedSha !== hashShouldBe) {
47 `Hashes does not correspond for segment ${filename}/${range}` +
48 `(expected: ${hashShouldBe} instead of ${calculatedSha})`
54 // ---------------------------------------------------------------------------
57 segmentValidatorFactory
60 // ---------------------------------------------------------------------------
62 function fetchSha256Segments (url: string) {
64 .then(res => res.json() as Promise<SegmentsJSON>)
66 console.error('Cannot get sha256 segments', err)
71 function sha256 (data?: ArrayBuffer) {
72 if (!data) return undefined
74 return window.crypto.subtle.digest('SHA-256', data)
77 // Thanks: https://stackoverflow.com/a/53307879
78 function bufferToEx (buffer?: ArrayBuffer) {
79 if (!buffer) return ''
82 const h = '0123456789abcdef'
83 const o = new Uint8Array(buffer)
85 o.forEach((v: any) => s += h[ v >> 4 ] + h[ v & 15 ])