]>
Commit | Line | Data |
---|---|---|
09209296 C |
1 | import { Segment } from 'p2p-media-loader-core' |
2 | import { basename } from 'path' | |
3 | ||
4 | function segmentValidatorFactory (segmentsSha256Url: string) { | |
5 | const segmentsJSON = fetchSha256Segments(segmentsSha256Url) | |
4c280004 | 6 | const regex = /bytes=(\d+)-(\d+)/ |
09209296 C |
7 | |
8 | return async function segmentValidator (segment: Segment) { | |
4c280004 C |
9 | const filename = basename(segment.url) |
10 | const captured = regex.exec(segment.range) | |
09209296 | 11 | |
4c280004 C |
12 | const range = captured[1] + '-' + captured[2] |
13 | ||
14 | const hashShouldBe = (await segmentsJSON)[filename][range] | |
09209296 | 15 | if (hashShouldBe === undefined) { |
4c280004 | 16 | throw new Error(`Unknown segment name ${filename}/${range} in segment validator`) |
09209296 C |
17 | } |
18 | ||
19 | const calculatedSha = bufferToEx(await sha256(segment.data)) | |
20 | if (calculatedSha !== hashShouldBe) { | |
4c280004 C |
21 | throw new Error( |
22 | `Hashes does not correspond for segment ${filename}/${range}` + | |
23 | `(expected: ${hashShouldBe} instead of ${calculatedSha})` | |
24 | ) | |
09209296 C |
25 | } |
26 | } | |
27 | } | |
28 | ||
29 | // --------------------------------------------------------------------------- | |
30 | ||
31 | export { | |
32 | segmentValidatorFactory | |
33 | } | |
34 | ||
35 | // --------------------------------------------------------------------------- | |
36 | ||
37 | function fetchSha256Segments (url: string) { | |
38 | return fetch(url) | |
39 | .then(res => res.json()) | |
40 | .catch(err => { | |
41 | console.error('Cannot get sha256 segments', err) | |
42 | return {} | |
43 | }) | |
44 | } | |
45 | ||
46 | function sha256 (data?: ArrayBuffer) { | |
47 | if (!data) return undefined | |
48 | ||
49 | return window.crypto.subtle.digest('SHA-256', data) | |
50 | } | |
51 | ||
52 | // Thanks: https://stackoverflow.com/a/53307879 | |
53 | function bufferToEx (buffer?: ArrayBuffer) { | |
54 | if (!buffer) return '' | |
55 | ||
56 | let s = '' | |
57 | const h = '0123456789abcdef' | |
58 | const o = new Uint8Array(buffer) | |
59 | ||
60 | o.forEach((v: any) => s += h[ v >> 4 ] + h[ v & 15 ]) | |
61 | ||
62 | return s | |
63 | } |