1 | import {
|
2 | BinaryWriter,
|
3 | createSerializeWire,
|
4 | InvalidFormatError,
|
5 | SerializableWire,
|
6 | SerializeWire,
|
7 | } from '@neo-one/client-common-esnext-esm';
|
8 | import { BinaryReader, DeserializeWireBaseOptions, DeserializeWireOptions } from '@neo-one/node-core-esnext-esm';
|
9 | import BN from 'bn.js';
|
10 | import { Address6 } from 'ip-address';
|
11 |
|
12 | export interface NetworkAddressAdd {
|
13 | readonly host: string;
|
14 | readonly port: number;
|
15 | readonly timestamp: number;
|
16 | readonly services: BN;
|
17 | }
|
18 |
|
19 | const BYTE_LENGTH = 16;
|
20 |
|
21 | export class NetworkAddress implements SerializableWire<NetworkAddress> {
|
22 | public static deserializeWireBase({ reader }: DeserializeWireBaseOptions): NetworkAddress {
|
23 | const timestamp = reader.readUInt32LE();
|
24 | const services = reader.readUInt64LE();
|
25 | const address = Address6.fromByteArray([...reader.readBytes(16)]) as Address6 | undefined | null;
|
26 | const port = reader.readUInt16BE();
|
27 |
|
28 | const canonical = address == undefined ? '' : (address.canonicalForm() as string | undefined | null);
|
29 |
|
30 | return new this({
|
31 | timestamp,
|
32 | services,
|
33 | host: canonical == undefined ? '' : canonical,
|
34 | port,
|
35 | });
|
36 | }
|
37 |
|
38 | public static deserializeWire(options: DeserializeWireOptions): NetworkAddress {
|
39 | return this.deserializeWireBase({
|
40 | context: options.context,
|
41 | reader: new BinaryReader(options.buffer),
|
42 | });
|
43 | }
|
44 |
|
45 | public static isValid(host: string): boolean {
|
46 | const address = this.getAddress6(host);
|
47 | if (address == undefined) {
|
48 | return false;
|
49 | }
|
50 |
|
51 | try {
|
52 | address.toByteArray();
|
53 |
|
54 | return true;
|
55 | } catch {
|
56 | return false;
|
57 | }
|
58 | }
|
59 |
|
60 | public static getAddress6(host: string): Address6 | null | undefined {
|
61 | const parts = host.split('.');
|
62 |
|
63 | return parts.length === 4 ? Address6.fromAddress4(host) : new Address6(host);
|
64 | }
|
65 |
|
66 | public readonly host: string;
|
67 | public readonly port: number;
|
68 | public readonly timestamp: number;
|
69 | public readonly services: BN;
|
70 | public readonly serializeWire: SerializeWire = createSerializeWire(this.serializeWireBase.bind(this));
|
71 |
|
72 | public constructor({ host, port, timestamp, services }: NetworkAddressAdd) {
|
73 | this.host = host;
|
74 | this.port = port;
|
75 | this.timestamp = timestamp;
|
76 | this.services = services;
|
77 | }
|
78 |
|
79 | public serializeWireBase(writer: BinaryWriter): void {
|
80 | const address = NetworkAddress.getAddress6(this.host);
|
81 | if (address == undefined) {
|
82 | throw new InvalidFormatError();
|
83 | }
|
84 | writer.writeUInt32LE(this.timestamp);
|
85 | writer.writeUInt64LE(this.services);
|
86 | const addressSerialized = Buffer.from(address.toByteArray());
|
87 | writer.writeBytes(Buffer.concat([Buffer.alloc(BYTE_LENGTH - addressSerialized.length, 0), addressSerialized]));
|
88 | writer.writeUInt16BE(this.port);
|
89 | }
|
90 | }
|