sen-ether-client 0.1.0
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.
- package/API.md +239 -0
- package/LICENSE +21 -0
- package/README.md +227 -0
- package/bin/node-sen-probe.js +426 -0
- package/bin/node-sen-scan.js +77 -0
- package/index.js +75 -0
- package/lib/bus.js +740 -0
- package/lib/client.js +634 -0
- package/lib/codec.js +501 -0
- package/lib/crc32.js +26 -0
- package/lib/discovery.js +439 -0
- package/lib/hash32.js +40 -0
- package/lib/protocol/generated.js +157 -0
- package/lib/sen.js +1346 -0
- package/lib/values.js +421 -0
- package/package.json +31 -0
- package/resources/protocol/ether/discovery.stl +19 -0
- package/resources/protocol/ether/runtime.stl +40 -0
- package/resources/protocol/kernel/basic_types.stl +274 -0
- package/resources/protocol/kernel/bus_protocol.stl +198 -0
- package/resources/protocol/kernel/type_specs.stl +554 -0
- package/resources/protocol/protocol.json +15 -0
- package/scripts/generate-protocol.mjs +111 -0
package/lib/values.js
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { SenBinaryReader, SenBinaryWriter } from './codec.js';
|
|
2
|
+
import { decodePropertyUpdateBuffer } from './bus.js';
|
|
3
|
+
|
|
4
|
+
function numberOrBigInt(value) {
|
|
5
|
+
return value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : value;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function normalizeTypeName(typeName) {
|
|
9
|
+
switch (typeName) {
|
|
10
|
+
case 'bool':
|
|
11
|
+
case 'booleanType':
|
|
12
|
+
return 'boolean';
|
|
13
|
+
case 'float':
|
|
14
|
+
case 'float32Type':
|
|
15
|
+
return 'f32';
|
|
16
|
+
case 'double':
|
|
17
|
+
case 'float64Type':
|
|
18
|
+
return 'f64';
|
|
19
|
+
case 'uint8Type':
|
|
20
|
+
return 'u8';
|
|
21
|
+
case 'int16Type':
|
|
22
|
+
return 'i16';
|
|
23
|
+
case 'uint16Type':
|
|
24
|
+
return 'u16';
|
|
25
|
+
case 'int32Type':
|
|
26
|
+
return 'i32';
|
|
27
|
+
case 'uint32Type':
|
|
28
|
+
return 'u32';
|
|
29
|
+
case 'int64Type':
|
|
30
|
+
return 'i64';
|
|
31
|
+
case 'uint64Type':
|
|
32
|
+
return 'u64';
|
|
33
|
+
case 'stringType':
|
|
34
|
+
return 'string';
|
|
35
|
+
case 'durationType':
|
|
36
|
+
return 'Duration';
|
|
37
|
+
case 'timestampType':
|
|
38
|
+
return 'TimeStamp';
|
|
39
|
+
default:
|
|
40
|
+
return typeName;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function findTypeSpec(typeRegistry, typeName) {
|
|
45
|
+
if (!typeRegistry) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
if (typeof typeRegistry.get === 'function') {
|
|
49
|
+
return typeRegistry.get(typeName);
|
|
50
|
+
}
|
|
51
|
+
return typeRegistry[typeName];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function classSpecData(spec) {
|
|
55
|
+
return spec?.data?.type === 'ClassTypeSpec' ? spec.data.value : undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function collectClassProperties(spec, typeRegistry, seen = new Set()) {
|
|
59
|
+
const data = classSpecData(spec);
|
|
60
|
+
if (!data || seen.has(spec.qualifiedName)) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
seen.add(spec.qualifiedName);
|
|
64
|
+
|
|
65
|
+
return [
|
|
66
|
+
...(data.parents ?? []).flatMap(parent => collectClassProperties(findTypeSpec(typeRegistry, parent), typeRegistry, seen)),
|
|
67
|
+
...data.properties
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function decodeEnum(reader, spec) {
|
|
72
|
+
const storage = spec.data.value.storageType;
|
|
73
|
+
const key = decodeValueFromReader(reader, storage);
|
|
74
|
+
const item = spec.data.value.enums.find(candidate => candidate.key === key);
|
|
75
|
+
return item?.name ?? key;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function decodeStruct(reader, spec, typeRegistry) {
|
|
79
|
+
const result = {};
|
|
80
|
+
for (const field of spec.data.value.fields) {
|
|
81
|
+
result[field.name] = decodeValueFromReader(reader, field.type, typeRegistry);
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function decodeSequence(reader, spec, typeRegistry) {
|
|
87
|
+
if (spec.data.value.elementType === 'u8' || spec.data.value.elementType === 'uint8Type') {
|
|
88
|
+
return reader.readBuffer();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const count = reader.readUInt32();
|
|
92
|
+
const values = [];
|
|
93
|
+
for (let i = 0; i < count; i += 1) {
|
|
94
|
+
values.push(decodeValueFromReader(reader, spec.data.value.elementType, typeRegistry));
|
|
95
|
+
}
|
|
96
|
+
return values;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function decodeVariant(reader, spec, typeRegistry) {
|
|
100
|
+
const key = reader.readUInt32();
|
|
101
|
+
const field = spec.data.value.fields.find(candidate => candidate.key === key);
|
|
102
|
+
if (!field) {
|
|
103
|
+
throw new TypeError(`unknown SEN variant key ${key} for ${spec.qualifiedName}`);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
key,
|
|
107
|
+
type: field.type,
|
|
108
|
+
value: decodeValueFromReader(reader, field.type, typeRegistry)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function decodeCustom(reader, spec, typeRegistry) {
|
|
113
|
+
switch (spec.data.type) {
|
|
114
|
+
case 'EnumTypeSpec':
|
|
115
|
+
return decodeEnum(reader, spec);
|
|
116
|
+
case 'StructTypeSpec':
|
|
117
|
+
return decodeStruct(reader, spec, typeRegistry);
|
|
118
|
+
case 'AliasTypeSpec':
|
|
119
|
+
return decodeValueFromReader(reader, spec.data.value.aliasedType, typeRegistry);
|
|
120
|
+
case 'OptionalTypeSpec':
|
|
121
|
+
return reader.readBool() ? decodeValueFromReader(reader, spec.data.value.type, typeRegistry) : null;
|
|
122
|
+
case 'QuantityTypeSpec':
|
|
123
|
+
return decodeValueFromReader(reader, spec.data.value.elementType.value, typeRegistry);
|
|
124
|
+
case 'SequenceTypeSpec':
|
|
125
|
+
return decodeSequence(reader, spec, typeRegistry);
|
|
126
|
+
case 'VariantTypeSpec':
|
|
127
|
+
return decodeVariant(reader, spec, typeRegistry);
|
|
128
|
+
default:
|
|
129
|
+
throw new TypeError(`decoding SEN type kind ${spec.data.type} is not implemented`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function writeInteger(writer, value, write) {
|
|
134
|
+
if (!Number.isInteger(Number(value))) {
|
|
135
|
+
throw new TypeError(`SEN integer value expected, got ${value}`);
|
|
136
|
+
}
|
|
137
|
+
write.call(writer, value);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function encodeEnum(writer, value, spec) {
|
|
141
|
+
const storage = spec.data.value.storageType;
|
|
142
|
+
let key = value;
|
|
143
|
+
if (typeof value === 'string') {
|
|
144
|
+
const item = spec.data.value.enums.find(candidate => candidate.name === value);
|
|
145
|
+
if (!item) {
|
|
146
|
+
throw new TypeError(`unknown SEN enum value ${value} for ${spec.qualifiedName}`);
|
|
147
|
+
}
|
|
148
|
+
key = item.key;
|
|
149
|
+
}
|
|
150
|
+
encodeValueToWriter(writer, key, storage);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function encodeStruct(writer, value, spec, typeRegistry) {
|
|
154
|
+
if (!value || typeof value !== 'object') {
|
|
155
|
+
throw new TypeError(`SEN struct ${spec.qualifiedName} expects an object value`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (const field of spec.data.value.fields) {
|
|
159
|
+
encodeValueToWriter(writer, value[field.name], field.type, typeRegistry);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function encodeSequence(writer, value, spec, typeRegistry) {
|
|
164
|
+
if (spec.data.value.elementType === 'u8' || spec.data.value.elementType === 'uint8Type') {
|
|
165
|
+
writer.writeBuffer(value);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!Array.isArray(value)) {
|
|
170
|
+
throw new TypeError(`SEN sequence ${spec.qualifiedName} expects an array value`);
|
|
171
|
+
}
|
|
172
|
+
writer.writeUInt32(value.length);
|
|
173
|
+
for (const item of value) {
|
|
174
|
+
encodeValueToWriter(writer, item, spec.data.value.elementType, typeRegistry);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function encodeVariant(writer, value, spec, typeRegistry) {
|
|
179
|
+
if (!value || typeof value !== 'object') {
|
|
180
|
+
throw new TypeError(`SEN variant ${spec.qualifiedName} expects { key|type, value }`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const field = value.key !== undefined
|
|
184
|
+
? spec.data.value.fields.find(candidate => candidate.key === value.key)
|
|
185
|
+
: spec.data.value.fields.find(candidate => candidate.type === value.type);
|
|
186
|
+
if (!field) {
|
|
187
|
+
throw new TypeError(`unknown SEN variant field for ${spec.qualifiedName}: ${value.key ?? value.type}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
writer.writeUInt32(field.key);
|
|
191
|
+
encodeValueToWriter(writer, value.value, field.type, typeRegistry);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function encodeCustom(writer, value, spec, typeRegistry) {
|
|
195
|
+
switch (spec.data.type) {
|
|
196
|
+
case 'EnumTypeSpec':
|
|
197
|
+
encodeEnum(writer, value, spec);
|
|
198
|
+
break;
|
|
199
|
+
case 'StructTypeSpec':
|
|
200
|
+
encodeStruct(writer, value, spec, typeRegistry);
|
|
201
|
+
break;
|
|
202
|
+
case 'AliasTypeSpec':
|
|
203
|
+
encodeValueToWriter(writer, value, spec.data.value.aliasedType, typeRegistry);
|
|
204
|
+
break;
|
|
205
|
+
case 'OptionalTypeSpec':
|
|
206
|
+
writer.writeBool(value !== null && value !== undefined);
|
|
207
|
+
if (value !== null && value !== undefined) {
|
|
208
|
+
encodeValueToWriter(writer, value, spec.data.value.type, typeRegistry);
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
case 'QuantityTypeSpec':
|
|
212
|
+
encodeValueToWriter(writer, value, spec.data.value.elementType.value, typeRegistry);
|
|
213
|
+
break;
|
|
214
|
+
case 'SequenceTypeSpec':
|
|
215
|
+
encodeSequence(writer, value, spec, typeRegistry);
|
|
216
|
+
break;
|
|
217
|
+
case 'VariantTypeSpec':
|
|
218
|
+
encodeVariant(writer, value, spec, typeRegistry);
|
|
219
|
+
break;
|
|
220
|
+
default:
|
|
221
|
+
throw new TypeError(`encoding SEN type kind ${spec.data.type} is not implemented`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function decodeValueFromReader(reader, typeName, typeRegistry) {
|
|
226
|
+
const normalized = normalizeTypeName(typeName);
|
|
227
|
+
|
|
228
|
+
switch (normalized) {
|
|
229
|
+
case 'u8':
|
|
230
|
+
return reader.readUInt8();
|
|
231
|
+
case 'i16':
|
|
232
|
+
return reader.readInt16();
|
|
233
|
+
case 'u16':
|
|
234
|
+
return reader.readUInt16();
|
|
235
|
+
case 'i32':
|
|
236
|
+
return reader.readInt32();
|
|
237
|
+
case 'u32':
|
|
238
|
+
return reader.readUInt32();
|
|
239
|
+
case 'i64':
|
|
240
|
+
case 'Duration':
|
|
241
|
+
case 'TimeStamp':
|
|
242
|
+
return reader.readInt64();
|
|
243
|
+
case 'u64':
|
|
244
|
+
return numberOrBigInt(reader.readUInt64());
|
|
245
|
+
case 'f32':
|
|
246
|
+
return reader.readFloat32();
|
|
247
|
+
case 'f64':
|
|
248
|
+
return reader.readFloat64();
|
|
249
|
+
case 'boolean':
|
|
250
|
+
return reader.readBool();
|
|
251
|
+
case 'string':
|
|
252
|
+
return reader.readString();
|
|
253
|
+
case 'Buffer':
|
|
254
|
+
case 'buffer':
|
|
255
|
+
case 'binary':
|
|
256
|
+
return reader.readBuffer();
|
|
257
|
+
default: {
|
|
258
|
+
const spec = findTypeSpec(typeRegistry, normalized);
|
|
259
|
+
if (!spec) {
|
|
260
|
+
throw new TypeError(`unknown SEN value type: ${normalized}`);
|
|
261
|
+
}
|
|
262
|
+
return decodeCustom(reader, spec, typeRegistry);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function encodeValueToWriter(writer, value, typeName, typeRegistry) {
|
|
268
|
+
const normalized = normalizeTypeName(typeName);
|
|
269
|
+
|
|
270
|
+
switch (normalized) {
|
|
271
|
+
case 'u8':
|
|
272
|
+
writeInteger(writer, value, writer.writeUInt8);
|
|
273
|
+
break;
|
|
274
|
+
case 'i16':
|
|
275
|
+
writeInteger(writer, value, writer.writeInt16);
|
|
276
|
+
break;
|
|
277
|
+
case 'u16':
|
|
278
|
+
writeInteger(writer, value, writer.writeUInt16);
|
|
279
|
+
break;
|
|
280
|
+
case 'i32':
|
|
281
|
+
writeInteger(writer, value, writer.writeInt32);
|
|
282
|
+
break;
|
|
283
|
+
case 'u32':
|
|
284
|
+
writeInteger(writer, value, writer.writeUInt32);
|
|
285
|
+
break;
|
|
286
|
+
case 'i64':
|
|
287
|
+
case 'Duration':
|
|
288
|
+
case 'TimeStamp':
|
|
289
|
+
writer.writeInt64(value);
|
|
290
|
+
break;
|
|
291
|
+
case 'u64':
|
|
292
|
+
writer.writeUInt64(value);
|
|
293
|
+
break;
|
|
294
|
+
case 'f32':
|
|
295
|
+
writer.writeFloat32(Number(value));
|
|
296
|
+
break;
|
|
297
|
+
case 'f64':
|
|
298
|
+
writer.writeFloat64(Number(value));
|
|
299
|
+
break;
|
|
300
|
+
case 'boolean':
|
|
301
|
+
writer.writeBool(Boolean(value));
|
|
302
|
+
break;
|
|
303
|
+
case 'string':
|
|
304
|
+
writer.writeString(value);
|
|
305
|
+
break;
|
|
306
|
+
case 'Buffer':
|
|
307
|
+
case 'buffer':
|
|
308
|
+
case 'binary':
|
|
309
|
+
writer.writeBuffer(value);
|
|
310
|
+
break;
|
|
311
|
+
default: {
|
|
312
|
+
const spec = findTypeSpec(typeRegistry, normalized);
|
|
313
|
+
if (!spec) {
|
|
314
|
+
throw new TypeError(`unknown SEN value type: ${normalized}`);
|
|
315
|
+
}
|
|
316
|
+
encodeCustom(writer, value, spec, typeRegistry);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function encodeValue(value, typeName, typeRegistry) {
|
|
323
|
+
const writer = new SenBinaryWriter();
|
|
324
|
+
encodeValueToWriter(writer, value, typeName, typeRegistry);
|
|
325
|
+
return writer.toBuffer();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function encodeArguments(values, argSpecs = [], typeRegistry) {
|
|
329
|
+
if ((values?.length ?? 0) !== argSpecs.length) {
|
|
330
|
+
throw new TypeError(`SEN method expects ${argSpecs.length} argument(s), got ${values?.length ?? 0}`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const writer = new SenBinaryWriter();
|
|
334
|
+
for (let i = 0; i < argSpecs.length; i += 1) {
|
|
335
|
+
encodeValueToWriter(writer, values[i], argSpecs[i].type, typeRegistry);
|
|
336
|
+
}
|
|
337
|
+
return writer.toBuffer();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function decodeArguments(buffer, argSpecs = [], typeRegistry) {
|
|
341
|
+
const reader = new SenBinaryReader(buffer);
|
|
342
|
+
const values = [];
|
|
343
|
+
for (const arg of argSpecs) {
|
|
344
|
+
values.push(decodeValueFromReader(reader, arg.type, typeRegistry));
|
|
345
|
+
}
|
|
346
|
+
if (reader.remaining() !== 0) {
|
|
347
|
+
throw new RangeError(`SEN argument decoder left ${reader.remaining()} unread bytes`);
|
|
348
|
+
}
|
|
349
|
+
return values;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function decodeValue(buffer, typeName, typeRegistry) {
|
|
353
|
+
const reader = new SenBinaryReader(buffer);
|
|
354
|
+
const value = decodeValueFromReader(reader, typeName, typeRegistry);
|
|
355
|
+
if (reader.remaining() !== 0) {
|
|
356
|
+
throw new RangeError(`SEN value decoder left ${reader.remaining()} unread bytes for ${typeName}`);
|
|
357
|
+
}
|
|
358
|
+
return value;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export function decodePropertyValues(buffer, classSpec, typeRegistry, options = {}) {
|
|
362
|
+
const strict = options.strict ?? false;
|
|
363
|
+
const propertyNames = options.propertyNames
|
|
364
|
+
? new Set([...options.propertyNames].map(name => String(name)))
|
|
365
|
+
: undefined;
|
|
366
|
+
const propertyIds = options.propertyIds
|
|
367
|
+
? new Set([...options.propertyIds].map(id => Number(id)))
|
|
368
|
+
: undefined;
|
|
369
|
+
const properties = collectClassProperties(classSpec, typeRegistry);
|
|
370
|
+
const propertiesById = new Map(properties.map(property => [property.id, property]));
|
|
371
|
+
|
|
372
|
+
const values = [];
|
|
373
|
+
for (const update of decodePropertyUpdateBuffer(buffer)) {
|
|
374
|
+
if (propertyIds && !propertyIds.has(update.id)) {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
const property = propertiesById.get(update.id);
|
|
378
|
+
if (!property) {
|
|
379
|
+
if (strict) {
|
|
380
|
+
throw new TypeError(`unknown SEN property id: ${update.id}`);
|
|
381
|
+
}
|
|
382
|
+
values.push({
|
|
383
|
+
...update,
|
|
384
|
+
name: undefined,
|
|
385
|
+
type: undefined,
|
|
386
|
+
value: undefined,
|
|
387
|
+
decoded: false
|
|
388
|
+
});
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (propertyNames && !propertyNames.has(property.name)) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
values.push({
|
|
398
|
+
...update,
|
|
399
|
+
name: property.name,
|
|
400
|
+
type: property.type,
|
|
401
|
+
property,
|
|
402
|
+
value: decodeValue(update.value, property.type, typeRegistry),
|
|
403
|
+
decoded: true
|
|
404
|
+
});
|
|
405
|
+
} catch (error) {
|
|
406
|
+
if (strict) {
|
|
407
|
+
throw error;
|
|
408
|
+
}
|
|
409
|
+
values.push({
|
|
410
|
+
...update,
|
|
411
|
+
name: property.name,
|
|
412
|
+
type: property.type,
|
|
413
|
+
property,
|
|
414
|
+
value: undefined,
|
|
415
|
+
error,
|
|
416
|
+
decoded: false
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return values;
|
|
421
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sen-ether-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Pure JavaScript SEN client for existing kernels over ether",
|
|
5
|
+
"senCompatibility": {
|
|
6
|
+
"kernelProtocolVersion": 9,
|
|
7
|
+
"etherProtocolVersion": 2
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "index.js",
|
|
11
|
+
"bin": {
|
|
12
|
+
"sen-ether-scan": "./bin/node-sen-scan.js",
|
|
13
|
+
"sen-ether-probe": "./bin/node-sen-probe.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"API.md",
|
|
17
|
+
"README.md",
|
|
18
|
+
"index.js",
|
|
19
|
+
"lib",
|
|
20
|
+
"bin",
|
|
21
|
+
"resources",
|
|
22
|
+
"scripts"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"exports": "./index.js",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"generate:protocol": "node ./scripts/generate-protocol.mjs",
|
|
28
|
+
"test": "node --test ./test/protocol.test.js ./test/codec.test.js ./test/discovery.test.js ./test/sen.test.js",
|
|
29
|
+
"test:integration": "node --test ./test/integration-*.test.js"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import "stl/sen/kernel/basic_types.stl"
|
|
2
|
+
|
|
3
|
+
package sen.components.ether;
|
|
4
|
+
|
|
5
|
+
struct Endpoint
|
|
6
|
+
{
|
|
7
|
+
ip : u32,
|
|
8
|
+
port : u16
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
sequence<Endpoint, 27> EnpointList;
|
|
12
|
+
|
|
13
|
+
struct SessionPresenceBeam
|
|
14
|
+
{
|
|
15
|
+
protocolVersion : u16,
|
|
16
|
+
info : sen.kernel.ProcessInfo,
|
|
17
|
+
beamPeriod : Duration,
|
|
18
|
+
endpoints : EnpointList
|
|
19
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import "stl/sen/kernel/basic_types.stl"
|
|
2
|
+
|
|
3
|
+
package sen.components.ether;
|
|
4
|
+
|
|
5
|
+
struct ProtocolVersion
|
|
6
|
+
{
|
|
7
|
+
kernel : u32,
|
|
8
|
+
ether : u32
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
struct Hello
|
|
12
|
+
{
|
|
13
|
+
info : sen.kernel.ProcessInfo,
|
|
14
|
+
udpPort : u16,
|
|
15
|
+
version : ProtocolVersion
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
struct Ready {}
|
|
19
|
+
|
|
20
|
+
struct BusJoined
|
|
21
|
+
{
|
|
22
|
+
participantId : u32,
|
|
23
|
+
busId : u32,
|
|
24
|
+
busName : string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
struct BusLeft
|
|
28
|
+
{
|
|
29
|
+
participantId : u32,
|
|
30
|
+
busId : u32,
|
|
31
|
+
busName : string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
variant ControlMessage
|
|
35
|
+
{
|
|
36
|
+
Hello,
|
|
37
|
+
Ready,
|
|
38
|
+
BusJoined,
|
|
39
|
+
BusLeft
|
|
40
|
+
}
|