/
producer.ts
109 lines (97 loc) · 3.1 KB
/
producer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { type Endpoint, produce, type Producer, type ProducerOptions } from "@ndn/endpoint";
import { Segment, Version } from "@ndn/naming-convention2";
import { Data, type Interest, Name, type NameLike, noopSigning, type Signer } from "@ndn/packet";
import { Encoder } from "@ndn/tlv";
import { type Metadata, MetadataKeyword } from "./metadata";
function makeName({ name }: Metadata, prefix?: NameLike): Name {
prefix = prefix ? Name.from(prefix) : name.getPrefix(-1);
return prefix.append(MetadataKeyword, Version.create(Date.now()), Segment.create(0));
}
/** Make metadata packet. */
export async function makeMetadataPacket(m: Metadata, {
prefix,
freshnessPeriod = 1,
signer = noopSigning,
}: makeMetadataPacket.Options = {}): Promise<Data> {
const data = new Data();
data.name = makeName(m, prefix);
data.content = Encoder.encode(m);
data.freshnessPeriod = freshnessPeriod;
await signer.sign(data);
return data;
}
export namespace makeMetadataPacket {
export interface Options {
/**
* Metadata packet prefix.
* @defaultValue `metadata.name.getPrefix(-1)`
*
* This should not contain `32=metadata` component.
*/
prefix?: NameLike;
/**
* FreshnessPeriod.
* @defaultValue 1
*/
freshnessPeriod?: number;
/**
* Data signer.
* @defaultValue noopSigning
*/
signer?: Signer;
}
}
/** Determine if an Interest is a discovery Interest. */
export function isDiscoveryInterest({ name, canBePrefix, mustBeFresh }: Interest): boolean {
return !!name.get(-1)?.equals(MetadataKeyword) && canBePrefix && mustBeFresh;
}
/** Serve metadata packet in a producer. */
export function serveMetadata(m: Metadata | (() => Metadata), opts: serveMetadata.Options = {}): Producer {
const {
prefix: prefixInput,
endpoint, // eslint-disable-line etc/no-deprecated
pOpts,
announcement, // eslint-disable-line etc/no-deprecated
} = opts;
const makeMetadata = typeof m === "function" ? m : () => m;
const prefix = makeName(makeMetadata(), prefixInput).getPrefix(-2);
return produce(prefix,
async (interest) => {
if (isDiscoveryInterest(interest) && interest.name.length === prefix.length) {
return makeMetadataPacket(makeMetadata(), {
signer: pOpts?.dataSigner,
...opts,
});
}
return undefined;
},
{
describe: `RDR-s(${prefix})`,
...endpoint?.pOpts,
...pOpts,
announcement,
});
}
export namespace serveMetadata {
export interface Options extends makeMetadataPacket.Options {
/**
* Endpoint for communication.
* @deprecated Specify `.pOpts`.
*/
endpoint?: Endpoint;
/**
* Producer options.
*
* @remarks
* - `.describe` defaults to "RDR-s" + prefix.
* - `.announcement` defaults to {@link makeMetadataPacket.Options.prefix}.
* - {@link makeMetadataPacket.Options.signer} defaults to `.dataSigner`.
*/
pOpts?: ProducerOptions;
/**
* Prefix to announce from producer.
* @deprecated Specify in `.pOpts.announcement`.
*/
announcement?: ProducerOptions.RouteAnnouncement;
}
}