aes70 2.0.14 → 2.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,16 @@
1
1
  /* eslint-env node */
2
2
 
3
3
  import { createSocket } from 'dgram';
4
- import { isIP } from 'net';
4
+ import { isIP, isIPv4 } from 'net';
5
5
  import { lookup } from 'dns';
6
+ import { Subscriptions } from '../utils/subscriptions.js';
7
+ import { subscribeEvent } from '../utils/subscribeEvent.js';
6
8
 
7
- function lookup_address(host) {
9
+ function lookup_address(host, family) {
8
10
  if (isIP(host)) return Promise.resolve(host);
9
11
 
10
12
  return new Promise((resolve, reject) => {
11
- lookup(host, { family: 4 }, (err, address) => {
13
+ lookup(host, { family }, (err, address) => {
12
14
  if (err) reject(err);
13
15
  else resolve(address);
14
16
  });
@@ -52,7 +54,11 @@ export class NodeUDP {
52
54
  this._inbuf = [];
53
55
 
54
56
  for (let i = 0; i < inbuf.length; i++) {
55
- onmessage(inbuf[i].buffer);
57
+ try {
58
+ onmessage(inbuf[i].buffer);
59
+ } catch (err) {
60
+ console.error(err);
61
+ }
56
62
  }
57
63
  }
58
64
 
@@ -73,30 +79,11 @@ export class NodeUDP {
73
79
  this.socket.send(Buffer.from(buf));
74
80
  }
75
81
 
76
- receiveMessage(timeout) {
77
- return new Promise((resolve, reject) => {
78
- if (this._error) {
79
- reject(this._error);
80
- } else if (this._inbuf.length) {
81
- resolve(this._inbuf.shift());
82
- } else {
83
- this.onmessage = (msg) => {
84
- this.onmessage = null;
85
- this.onerror = null;
86
- resolve(msg);
87
- };
88
- this.onerror = (err) => {
89
- this.onmessage = null;
90
- this.onerror = null;
91
- reject(err);
92
- };
93
- }
94
- });
95
- }
96
-
97
82
  close() {
98
- this.socket.close();
99
- this.socket = null;
83
+ if (this.socket) {
84
+ this.socket.close();
85
+ this.socket = null;
86
+ }
100
87
  }
101
88
 
102
89
  constructor(socket) {
@@ -114,14 +101,63 @@ export class NodeUDP {
114
101
  });
115
102
  }
116
103
 
117
- static connect(host, port, type) {
118
- return lookup_address(host).then((ip) => {
119
- return new Promise((resolve, reject) => {
120
- const socket = createSocket(type || 'udp4');
104
+ /**
105
+ * Creates a new udp socket and connects it to the target address.
106
+ * @param {string} options.host
107
+ * The hostname or ip address to connect to.
108
+ * @param {number} options.port
109
+ * The port.
110
+ * @param {'udp4' | 'udp6'} [options.type]
111
+ * The ip protocol to use. This is only relevant if host is
112
+ * not an ip address and hostname lookup is used.
113
+ * @param {Abortsignal} [options.signal]
114
+ * An optional AbortSignal to abort the connect operation.
115
+ * @returns
116
+ */
117
+ static connect(options) {
118
+ const { host, port, type, signal } = options;
119
+
120
+ signal?.throwIfAborted();
121
+
122
+ const subscriptions = new Subscriptions();
123
+
124
+ return new Promise((resolve, reject) => {
125
+ let socket;
126
+
127
+ if (signal) {
128
+ subscriptions.add(
129
+ subscribeEvent(signal, 'abort', (reason) => {
130
+ const err = signal.reason;
131
+ reject(err);
132
+ })
133
+ );
134
+ }
135
+
136
+ const lookupFamily =
137
+ type === 'udp4' ? 4 : type === 'udp6' ? 6 : undefined;
138
+ lookup_address(host, lookupFamily).then((ip) => {
139
+ if (signal?.aborted) {
140
+ // IF the abort signal was triggered during the ip lookup,
141
+ // we have to simply ignore the resolve result.
142
+ return;
143
+ }
144
+ const type = isIPv4(ip) ? 'udp4' : 'udp6';
145
+ socket = createSocket(type);
146
+
147
+ if (signal) {
148
+ subscriptions.add(
149
+ subscribeEvent(signal, 'abort', () => {
150
+ socket.close();
151
+ })
152
+ );
153
+ }
154
+
121
155
  const onerror = function (ev) {
122
156
  reject(ev);
157
+ socket.close();
123
158
  };
124
- socket.on('error', onerror);
159
+ subscriptions.add(subscribeEvent(socket, 'error', onerror));
160
+
125
161
  socket.bind(
126
162
  {
127
163
  exclusive: true,
@@ -129,12 +165,11 @@ export class NodeUDP {
129
165
  () => {
130
166
  socket.on('connect', () => {
131
167
  resolve(new this(socket));
132
- socket.removeListener('error', onerror);
133
168
  });
134
- socket.connect(port, host);
169
+ socket.connect(port, ip);
135
170
  }
136
171
  );
137
- });
138
- });
172
+ }, reject);
173
+ }).finally(() => subscriptions.unsubscribe());
139
174
  }
140
175
  }
@@ -56,8 +56,7 @@ export class Property {
56
56
  * @returns {Function} The getter. If none could be found, null is returned.
57
57
  */
58
58
  getter(o, no_bind) {
59
- let name = this.name;
60
- let i = 0;
59
+ const name = this.name;
61
60
  const aliases = this.aliases;
62
61
  const accessors = this.accessors;
63
62
 
@@ -99,10 +98,13 @@ export class Property {
99
98
  return no_bind ? fun : fun.bind(o);
100
99
  }
101
100
 
102
- do {
101
+ // iterate all possible names
102
+ const possibleNames = aliases ? [name, ...aliases] : [name];
103
+
104
+ for (const possibleName of possibleNames) {
103
105
  if (this.static) {
104
106
  const c = o.constructor;
105
- const v = c[name];
107
+ const v = c[possibleName];
106
108
 
107
109
  if (v !== void 0) {
108
110
  return function () {
@@ -110,16 +112,11 @@ export class Property {
110
112
  };
111
113
  }
112
114
  } else {
113
- const fun = o['Get' + name];
115
+ const fun = o['Get' + possibleName];
114
116
 
115
117
  if (fun) return no_bind ? fun : fun.bind(o);
116
118
  }
117
-
118
- if (aliases && i < aliases.length) {
119
- name = aliases[i++];
120
- continue;
121
- }
122
- } while (false);
119
+ }
123
120
 
124
121
  return null;
125
122
  }
@@ -135,20 +132,15 @@ export class Property {
135
132
  setter(o, no_bind) {
136
133
  if (this.readonly || this.static) return null;
137
134
 
138
- let name = this.name,
139
- i = 0;
135
+ const name = this.name;
140
136
  const aliases = this.aliases;
137
+ const possibleNames = aliases ? [name, ...aliases] : [name];
141
138
 
142
- do {
143
- const fun = o['Set' + name];
139
+ for (const possibleName of possibleNames) {
140
+ const fun = o['Set' + possibleName];
144
141
 
145
142
  if (fun) return no_bind ? fun : fun.bind(o);
146
-
147
- if (aliases && i < aliases.length) {
148
- name = aliases[i++];
149
- continue;
150
- }
151
- } while (false);
143
+ }
152
144
 
153
145
  return null;
154
146
  }
package/src/events.js CHANGED
@@ -4,12 +4,13 @@
4
4
  export class Events {
5
5
  constructor() {
6
6
  this.event_handlers = new Map();
7
+ this.event_handlers_cleared = false;
7
8
  }
8
9
 
9
10
  /**
10
11
  * Emit an event.
11
12
  *
12
- * @param {String} name - Name of the event.
13
+ * @param {string} name - Name of the event.
13
14
  * @param {...*} args - Extra arguments.
14
15
  */
15
16
  emit(name) {
@@ -30,7 +31,7 @@ export class Events {
30
31
  /**
31
32
  * Subscribe to an event.
32
33
  *
33
- * @param {String} name - Name of the event.
34
+ * @param {string} name - Name of the event.
34
35
  * @param {Function} cb - Callback function.
35
36
  */
36
37
  on(name, cb) {
@@ -54,14 +55,17 @@ export class Events {
54
55
  /**
55
56
  * Removes an event handler.
56
57
  *
57
- * @param {String} name - Name of the event.
58
+ * @param {string} name - Name of the event.
58
59
  * @param {Function} cb - Callback function.
59
60
  */
60
61
  removeEventListener(name, cb) {
61
62
  const handlers = this.event_handlers.get(name);
62
63
 
63
64
  if (!handlers || !handlers.has(cb)) {
64
- throw new Error('removeEventListeners(): not installed.');
65
+ if (!this.event_handlers_cleared) {
66
+ console.warn('removeEventListeners(): not installed:', name, cb);
67
+ }
68
+ return;
65
69
  }
66
70
 
67
71
  handlers.delete(cb);
@@ -70,7 +74,7 @@ export class Events {
70
74
  /**
71
75
  * Removes an event handler.
72
76
  *
73
- * @param {strign} name
77
+ * @param {string} name
74
78
  * @param {Function} cb
75
79
  */
76
80
  off(name, cb) {
@@ -82,6 +86,7 @@ export class Events {
82
86
  */
83
87
  removeAllEventListeners() {
84
88
  this.event_handlers.clear();
89
+ this.event_handlers_cleared = true;
85
90
  }
86
91
 
87
92
  /**
@@ -0,0 +1,32 @@
1
+ function addEvent(target, name, callback) {
2
+ if (target.addEventListener) {
3
+ target.addEventListener(name, callback);
4
+ } else if (target.on) {
5
+ target.on(name, callback);
6
+ } else {
7
+ throw new TypeError('Unsupported event target ', target);
8
+ }
9
+ }
10
+
11
+ function removeEvent(target, name, callback) {
12
+ if (target.removeEventListener) {
13
+ target.removeEventListener(name, callback);
14
+ } else if (target.off) {
15
+ target.off(name, callback);
16
+ } else {
17
+ throw new TypeError('Unsupported event target ', target);
18
+ }
19
+ }
20
+
21
+ /**
22
+ *
23
+ * @param {EventTarget|Events} target
24
+ * @param {string} name
25
+ * @param {callback} callback
26
+ */
27
+ export function subscribeEvent(target, name, callback) {
28
+ addEvent(target, name, callback);
29
+ return () => {
30
+ removeEvent(target, name, callback);
31
+ };
32
+ }
@@ -0,0 +1,27 @@
1
+ export class Subscriptions {
2
+ constructor() {
3
+ this._callbacks = [];
4
+ }
5
+
6
+ /**
7
+ * Add a subscription.
8
+ *
9
+ * @param {Function[]} cbs
10
+ */
11
+ add(...cbs) {
12
+ cbs.forEach((cb) => {
13
+ this._callbacks.push(cb);
14
+ });
15
+ }
16
+
17
+ unsubscribe() {
18
+ this._callbacks.forEach((cb) => {
19
+ try {
20
+ cb();
21
+ } catch (err) {
22
+ console.error(err);
23
+ }
24
+ });
25
+ this._callbacks.length = 0;
26
+ }
27
+ }
@@ -0,0 +1,123 @@
1
+ function isItTime(target, now) {
2
+ // We are ok with 1ms accuracy.
3
+ return target - now < 1;
4
+ }
5
+
6
+ export class Timer {
7
+ constructor(callback, getNow) {
8
+ this._callback = callback;
9
+ this._getNow = getNow;
10
+ this._targetTime = undefined;
11
+ this._timerId = undefined;
12
+ this._timerAt = undefined;
13
+ }
14
+
15
+ poll() {
16
+ const now = this._getNow();
17
+
18
+ if (this._targetTime === undefined) return;
19
+
20
+ if (isItTime(this._targetTime, now)) {
21
+ this._targetTime = undefined;
22
+ try {
23
+ this._callback();
24
+ } catch (err) {
25
+ console.error('Timer callback threw an exception', err);
26
+ }
27
+ } else {
28
+ this._reschedule();
29
+ }
30
+ }
31
+
32
+ _reschedule() {
33
+ const target = this._targetTime;
34
+ const interval = target - this._getNow();
35
+
36
+ if (this._timerId !== undefined) {
37
+ if (target >= this._timerAt) {
38
+ // The timer will fire before target. We will then reschedule it.
39
+ return;
40
+ }
41
+
42
+ clearTimeout(this._timerId);
43
+ this._timerId = undefined;
44
+ }
45
+
46
+ this._timerAt = target;
47
+ this._timerId = setTimeout(() => {
48
+ this._timerId = undefined;
49
+ this._timerAt = undefined;
50
+ this.poll();
51
+ }, Math.max(0, interval));
52
+ }
53
+
54
+ /**
55
+ *
56
+ * @param {number} interval
57
+ * Interval in milliseconds.
58
+ */
59
+ scheduleIn(interval) {
60
+ if (!(interval >= 0)) {
61
+ throw new TypeError(`Expected positive interval.`);
62
+ }
63
+
64
+ this._targetTime = this._getNow() + interval;
65
+ this._reschedule();
66
+ }
67
+
68
+ /**
69
+ * Schedule the timer in a given number of milliseconds. If the timer
70
+ * is already running and scheduled to run before, do not modify it.
71
+ *
72
+ * @param {number} interval
73
+ */
74
+ scheduleDeadlineIn(interval) {
75
+ if (!(interval >= 0)) {
76
+ throw new TypeError(`Expected positive interval.`);
77
+ }
78
+
79
+ const target = this._getNow() + interval;
80
+
81
+ if (this._targetTime !== undefined && this._targetTime <= target) {
82
+ this.poll();
83
+ return;
84
+ }
85
+
86
+ this.scheduleAt(target);
87
+ }
88
+
89
+ /**
90
+ *
91
+ * @param {number} target
92
+ * Target time in milliseconds.
93
+ */
94
+ scheduleAt(target) {
95
+ if (!(target >= 0)) {
96
+ throw new TypeError();
97
+ }
98
+
99
+ this._targetTime = target;
100
+ this._reschedule();
101
+ }
102
+
103
+ stop() {
104
+ this._targetTime = undefined;
105
+ }
106
+
107
+ cancel() {
108
+ this.stop();
109
+ this._clearTimeout();
110
+ }
111
+
112
+ _clearTimeout() {
113
+ if (this._timerId) {
114
+ clearTimeout(this._timerId);
115
+ this._timerId = undefined;
116
+ this._timerAt = undefined;
117
+ }
118
+ }
119
+
120
+ dispose() {
121
+ this.cancel();
122
+ }
123
+ }