unetjs 5.0.1 → 6.0.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/README.md +8 -40
- package/dist/cjs/unet.cjs +501 -296
- package/dist/esm/unet.js +501 -295
- package/dist/unetjs.js +500 -295
- package/dist/unetjs.js.map +1 -1
- package/dist/unetjs.min.js +1 -1
- package/dist/unetjs.min.js.map +1 -1
- package/package.json +20 -19
package/dist/cjs/unet.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/* unet.js
|
|
1
|
+
/* unet.js v6.0.0 2026-04-01T02:42:00.135Z */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
/* fjage.js v2.
|
|
5
|
+
/* fjage.js v2.3.0 */
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* An action represented by a message. The performative actions are a subset of the
|
|
@@ -1846,6 +1846,60 @@ const ParameterReq = MessageClass('org.arl.fjage.param.ParameterReq');
|
|
|
1846
1846
|
*/
|
|
1847
1847
|
MessageClass('org.arl.fjage.param.ParameterRsp');
|
|
1848
1848
|
|
|
1849
|
+
/**
|
|
1850
|
+
* Request to write contents to a file, or delete a file.
|
|
1851
|
+
*
|
|
1852
|
+
* @typedef {Message} PutFileReq
|
|
1853
|
+
* @property {string} filename - name of the file to be written to or deleted
|
|
1854
|
+
* @property {number} [content] - content to be written to the file as a byte array. If not provided, the file will be deleted.
|
|
1855
|
+
* @property {number} [offset=0] - offset in the file to write the content to.
|
|
1856
|
+
* @exports PutFileReq
|
|
1857
|
+
*/
|
|
1858
|
+
const PutFileReq = MessageClass('org.arl.fjage.shell.PutFileReq');
|
|
1859
|
+
|
|
1860
|
+
|
|
1861
|
+
/**
|
|
1862
|
+
* Request to read a file or a directory.
|
|
1863
|
+
*
|
|
1864
|
+
* If the filename specified represents a directory, then the contents of the
|
|
1865
|
+
* directory (list of files) are returned as a tab separated string with:
|
|
1866
|
+
* filename, file size, last modification time.
|
|
1867
|
+
*
|
|
1868
|
+
* The time is represented as epoch time (milliseconds since 1 Jan 1970).
|
|
1869
|
+
*
|
|
1870
|
+
* @typedef {Message} GetFileReq
|
|
1871
|
+
* @property {string} filename - name of the file or directory to be read
|
|
1872
|
+
* @property {number} [offset=0] - offset in the file to read from (ignored for directories)
|
|
1873
|
+
* @property {number} [length=0] - number of bytes to read from the file (ignored for directories). If 0,
|
|
1874
|
+
* the entire file will be read.
|
|
1875
|
+
* @exports GetFileReq
|
|
1876
|
+
*/
|
|
1877
|
+
const GetFileReq = MessageClass('org.arl.fjage.shell.GetFileReq');
|
|
1878
|
+
|
|
1879
|
+
/**
|
|
1880
|
+
* Response to a {@link GetFileReq}, with the contents of the file or the directory.
|
|
1881
|
+
*
|
|
1882
|
+
* @typedef {Message} GetFileRsp
|
|
1883
|
+
* @property {string} filename - name of the file or directory that was read
|
|
1884
|
+
* @property {number} [content] - content of the file as a byte array. If the filename represents a directory,
|
|
1885
|
+
* the content consists of a list of files (one file per line). Each line starts with the filename
|
|
1886
|
+
* (with a trailing "/" if it is a directory), "\t", file size in bytes, "\t", and last modification date.
|
|
1887
|
+
* @property {number} [offset=0] - offset in the file that the content corresponds to (ignored for directories)
|
|
1888
|
+
* @property {boolean} [directory=false] - indicates if the filename represents a directory
|
|
1889
|
+
* @exports GetFileRsp
|
|
1890
|
+
*/
|
|
1891
|
+
const GetFileRsp = MessageClass('org.arl.fjage.shell.GetFileRsp');
|
|
1892
|
+
|
|
1893
|
+
/**
|
|
1894
|
+
* Request to execute shell command/script.
|
|
1895
|
+
*
|
|
1896
|
+
* @typedef {Message} ShellExecReq
|
|
1897
|
+
* @property {string} command - shell command or script to be executed
|
|
1898
|
+
* @property {boolean} ans - indicates if the response to this request should include the output of the command/script execution
|
|
1899
|
+
* @exports ShellExecReq
|
|
1900
|
+
*/
|
|
1901
|
+
const ShellExecReq = MessageClass('org.arl.fjage.shell.ShellExecReq');
|
|
1902
|
+
|
|
1849
1903
|
/**
|
|
1850
1904
|
* Services supported by fjage agents.
|
|
1851
1905
|
*/
|
|
@@ -1858,9 +1912,15 @@ init();
|
|
|
1858
1912
|
const DatagramReq$1 = MessageClass('org.arl.unet.DatagramReq');
|
|
1859
1913
|
const DatagramNtf$1 = MessageClass('org.arl.unet.DatagramNtf');
|
|
1860
1914
|
const TxFrameReq = MessageClass('org.arl.unet.phy.TxFrameReq', DatagramReq$1);
|
|
1861
|
-
const RxFrameNtf
|
|
1915
|
+
const RxFrameNtf = MessageClass('org.arl.unet.phy.RxFrameNtf', DatagramNtf$1);
|
|
1862
1916
|
const BasebandSignal = MessageClass('org.arl.unet.bb.BasebandSignal');
|
|
1863
1917
|
|
|
1918
|
+
const UnetTopics = {
|
|
1919
|
+
'PARAMCHANGE' : 'org.arl.unet.Topics.PARAMCHANGE', // Topic for parameter change notification.
|
|
1920
|
+
'LIFECYCLE' : 'org.arl.unet.Topics.LIFECYCLE', // Topic for agent lifecycle notification.
|
|
1921
|
+
'DATAGRAM' : 'org.arl.unet.Topics.DATAGRAM', // Topic for incoming datagram notification.
|
|
1922
|
+
};
|
|
1923
|
+
|
|
1864
1924
|
let UnetServices = {
|
|
1865
1925
|
'NODE_INFO': 'org.arl.unet.Services.NODE_INFO',
|
|
1866
1926
|
'ADDRESS_RESOLUTION': 'org.arl.unet.Services.ADDRESS_RESOLUTION',
|
|
@@ -1905,6 +1965,13 @@ let Protocol = {
|
|
|
1905
1965
|
* @typedef {Object.<string, MessageClass>} UnetMessages
|
|
1906
1966
|
*/
|
|
1907
1967
|
let UnetMessages = {
|
|
1968
|
+
|
|
1969
|
+
// fjage
|
|
1970
|
+
'PutFileReq' : PutFileReq,
|
|
1971
|
+
'GetFileReq' : GetFileReq,
|
|
1972
|
+
'GetFileRsp' : GetFileRsp,
|
|
1973
|
+
'ShellExecReq' : ShellExecReq,
|
|
1974
|
+
|
|
1908
1975
|
// unet
|
|
1909
1976
|
'TestReportNtf' : MessageClass('org.arl.unet.TestReportNtf'),
|
|
1910
1977
|
'AbnormalTerminationNtf' : MessageClass('org.arl.unet.AbnormalTerminationNtf'),
|
|
@@ -1917,6 +1984,7 @@ let UnetMessages = {
|
|
|
1917
1984
|
'DatagramNtf' : MessageClass('org.arl.unet.DatagramNtf'),
|
|
1918
1985
|
'DatagramProgressNtf' : MessageClass('org.arl.unet.DatagramProgressNtf'),
|
|
1919
1986
|
'DatagramReq' : MessageClass('org.arl.unet.DatagramReq'),
|
|
1987
|
+
'DatagramTransmissionNtf': MessageClass('org.arl.unet.DatagramTransmissionNtf'),
|
|
1920
1988
|
'ParamChangeNtf' : MessageClass('org.arl.unet.ParamChangeNtf'),
|
|
1921
1989
|
'RefuseRsp' : MessageClass('org.arl.unet.RefuseRsp'),
|
|
1922
1990
|
'FailureNtf' : MessageClass('org.arl.unet.FailureNtf'),
|
|
@@ -1930,9 +1998,9 @@ let UnetMessages = {
|
|
|
1930
1998
|
|
|
1931
1999
|
// phy
|
|
1932
2000
|
'FecDecodeReq' : MessageClass('org.arl.unet.phy.FecDecodeReq'),
|
|
1933
|
-
'RxSWiG1FrameNtf' : MessageClass('org.arl.unet.phy.RxSWiG1FrameNtf', RxFrameNtf
|
|
2001
|
+
'RxSWiG1FrameNtf' : MessageClass('org.arl.unet.phy.RxSWiG1FrameNtf', RxFrameNtf),
|
|
1934
2002
|
'TxSWiG1FrameReq' : MessageClass('org.arl.unet.phy.TxSWiG1FrameReq', TxFrameReq),
|
|
1935
|
-
'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf', RxFrameNtf
|
|
2003
|
+
'RxJanusFrameNtf' : MessageClass('org.arl.unet.phy.RxJanusFrameNtf', RxFrameNtf),
|
|
1936
2004
|
'TxJanusFrameReq' : MessageClass('org.arl.unet.phy.TxJanusFrameReq', TxFrameReq),
|
|
1937
2005
|
'BadFrameNtf' : MessageClass('org.arl.unet.phy.BadFrameNtf'),
|
|
1938
2006
|
'BadRangeNtf' : MessageClass('org.arl.unet.phy.BadRangeNtf'),
|
|
@@ -1986,6 +2054,7 @@ let UnetMessages = {
|
|
|
1986
2054
|
'RemoteFileGetReq' : MessageClass('org.arl.unet.remote.RemoteFileGetReq'),
|
|
1987
2055
|
'RemoteFileNtf' : MessageClass('org.arl.unet.remote.RemoteFileNtf'),
|
|
1988
2056
|
'RemoteFilePutReq' : MessageClass('org.arl.unet.remote.RemoteFilePutReq'),
|
|
2057
|
+
'RemoteDeliveryNtf' : MessageClass('org.arl.unet.remote.RemoteDeliveryNtf'),
|
|
1989
2058
|
'RemoteSuccessNtf' : MessageClass('org.arl.unet.remote.RemoteSuccessNtf'),
|
|
1990
2059
|
'RemoteTextNtf' : MessageClass('org.arl.unet.remote.RemoteTextNtf'),
|
|
1991
2060
|
'RemoteTextReq' : MessageClass('org.arl.unet.remote.RemoteTextReq'),
|
|
@@ -2040,243 +2109,33 @@ function _initConv(lat){
|
|
|
2040
2109
|
return [xScale, yScale];
|
|
2041
2110
|
}
|
|
2042
2111
|
|
|
2043
|
-
|
|
2044
|
-
* A message which requests the transmission of the datagram from the Unet
|
|
2045
|
-
*
|
|
2046
|
-
* @typedef {Message} DatagramReq
|
|
2047
|
-
* @property {number[]} data - data as an Array of bytes
|
|
2048
|
-
* @property {number} from - from/source node address
|
|
2049
|
-
* @property {number} to - to/destination node address
|
|
2050
|
-
* @property {number} protocol - protocol number to be used to send this Datagram
|
|
2051
|
-
* @property {boolean} reliability - true if Datagram should be reliable, false if unreliable
|
|
2052
|
-
* @property {number} ttl - time-to-live for the datagram. Time-to-live is advisory, and an agent may choose it ignore it
|
|
2053
|
-
*/
|
|
2054
|
-
|
|
2055
|
-
/**
|
|
2056
|
-
* Notification of received datagram message received by the Unet node.
|
|
2057
|
-
*
|
|
2058
|
-
* @typedef {Message} DatagramNtf
|
|
2059
|
-
* @property {number[]} data - data as an Array of bytes
|
|
2060
|
-
* @property {number} from - from/source node address
|
|
2061
|
-
* @property {number} to - to/destination node address
|
|
2062
|
-
* @property {number} protocol - protocol number to be used to send this Datagram
|
|
2063
|
-
* @property {number} ttl - time-to-live for the datagram. Time-to-live is advisory, and an agent may choose it ignore it
|
|
2064
|
-
*/
|
|
2065
|
-
|
|
2066
|
-
/**
|
|
2067
|
-
* An identifier for an agent or a topic.
|
|
2068
|
-
* @external AgentID
|
|
2069
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2070
|
-
*/
|
|
2071
|
-
|
|
2072
|
-
/**
|
|
2073
|
-
* Services supported by fjage agents.
|
|
2074
|
-
* @external Services
|
|
2075
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2076
|
-
*/
|
|
2077
|
-
|
|
2078
|
-
/**
|
|
2079
|
-
* An action represented by a message.
|
|
2080
|
-
* @external Performative
|
|
2081
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2082
|
-
*/
|
|
2083
|
-
|
|
2084
|
-
/**
|
|
2085
|
-
* Function to creates a unqualified message class based on a fully qualified name.
|
|
2086
|
-
* @external MessageClass
|
|
2087
|
-
* @see {@link https://org-arl.github.io/fjage/jsdoc/|fjåge.js Documentation}
|
|
2088
|
-
*/
|
|
2089
|
-
|
|
2090
|
-
/**
|
|
2091
|
-
* A caching CachingAgentID which caches Agent parameters locally.
|
|
2092
|
-
*
|
|
2093
|
-
* @class
|
|
2094
|
-
* @extends AgentID
|
|
2095
|
-
* @param {string | AgentID} name - name of the agent or an AgentID to copy
|
|
2096
|
-
* @param {boolean} topic - name of topic
|
|
2097
|
-
* @param {Gateway} owner - Gateway owner for this AgentID
|
|
2098
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2099
|
-
*
|
|
2100
|
-
*/
|
|
2101
|
-
class CachingAgentID extends AgentID {
|
|
2102
|
-
|
|
2103
|
-
constructor(name, topic, owner, greedy=true) {
|
|
2104
|
-
if (name instanceof AgentID) {
|
|
2105
|
-
super(name.getName(), name.topic, name.owner);
|
|
2106
|
-
} else {
|
|
2107
|
-
super(name, topic, owner);
|
|
2108
|
-
}
|
|
2109
|
-
this.greedy = greedy;
|
|
2110
|
-
this.cache = {};
|
|
2111
|
-
this.specialParams = ['name', 'version'];
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
/**
|
|
2115
|
-
* Sets parameter(s) on the Agent referred to by this AgentID, and caches the parameter(s).
|
|
2116
|
-
*
|
|
2117
|
-
* @param {(string|string[])} params - parameters name(s) to be set
|
|
2118
|
-
* @param {(Object|Object[])} values - parameters value(s) to be set
|
|
2119
|
-
* @param {number} [index=-1] - index of parameter(s) to be set
|
|
2120
|
-
* @param {number} [timeout=5000] - timeout for the response
|
|
2121
|
-
* @returns {Promise<(Object|Object[])>} - a promise which returns the new value(s) of the parameters
|
|
2122
|
-
*/
|
|
2123
|
-
async set(params, values, index=-1, timeout=5000) {
|
|
2124
|
-
let s = await super.set(params, values, index, timeout);
|
|
2125
|
-
this._updateCache(params, s, index);
|
|
2126
|
-
return s;
|
|
2127
|
-
}
|
|
2128
|
-
|
|
2129
|
-
/**
|
|
2130
|
-
* Gets parameter(s) on the Agent referred to by this AgentID, getting them from the cache if possible.
|
|
2131
|
-
*
|
|
2132
|
-
* @param {(string|string[])} params - parameters name(s) to be fetched
|
|
2133
|
-
* @param {number} [index=-1] - index of parameter(s) to be fetched
|
|
2134
|
-
* @param {number} [timeout=5000] - timeout for the response
|
|
2135
|
-
* @param {number} [maxage=5000] - maximum age of the cached result to retreive
|
|
2136
|
-
* @returns {Promise<(Object|Object[])>} - a promise which returns the value(s) of the parameters
|
|
2137
|
-
*/
|
|
2138
|
-
async get(params, index=-1, timeout=5000, maxage=5000) {
|
|
2139
|
-
if (this._isCached(params, index, maxage)) return this._getCache(params, index);
|
|
2140
|
-
if (this.greedy &&
|
|
2141
|
-
!(Array.isArray(params) && [...new Set([...params, ...this.specialParams])].length!=0) &&
|
|
2142
|
-
!this.specialParams.includes(params)) {
|
|
2143
|
-
let rsp = await super.get(null, index, timeout);
|
|
2144
|
-
this._updateCache(null, rsp, index);
|
|
2145
|
-
if (!rsp) return Array.isArray(params) ? new Array(params.length).fill(null) : null;
|
|
2146
|
-
if (!params) return rsp;
|
|
2147
|
-
else if (Array.isArray(params)) {
|
|
2148
|
-
return params.map(p => {
|
|
2149
|
-
let f = Object.keys(rsp).find(rv => this._toNamed(rv) === p);
|
|
2150
|
-
return f ? rsp[f] : null;
|
|
2151
|
-
});
|
|
2152
|
-
} else {
|
|
2153
|
-
let f = Object.keys(rsp).find(rv => this._toNamed(rv) === params);
|
|
2154
|
-
return f ? rsp[f] : null;
|
|
2155
|
-
}
|
|
2156
|
-
} else {
|
|
2157
|
-
let r = await super.get(params, index, timeout);
|
|
2158
|
-
this._updateCache(params, r, index);
|
|
2159
|
-
return r;
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
|
-
|
|
2163
|
-
_updateCache(params, vals, index) {
|
|
2164
|
-
if (vals == null || Array.isArray(vals) && vals.every(v => v == null)) return;
|
|
2165
|
-
if (params == null) {
|
|
2166
|
-
params = Object.keys(vals);
|
|
2167
|
-
vals = Object.values(vals);
|
|
2168
|
-
} else if (!Array.isArray(params)) params = [params];
|
|
2169
|
-
if (!Array.isArray(vals)) vals = [vals];
|
|
2170
|
-
params = params.map(this._toNamed);
|
|
2171
|
-
if (this.cache[index.toString()] === undefined) this.cache[index.toString()] = {};
|
|
2172
|
-
let c = this.cache[index.toString()];
|
|
2173
|
-
for (let i = 0; i < params.length; i++) {
|
|
2174
|
-
if (c[params[i]] === undefined) c[params[i]] = {};
|
|
2175
|
-
c[params[i]].value = vals[i];
|
|
2176
|
-
c[params[i]].ctime = Date.now();
|
|
2177
|
-
}
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
|
-
_isCached(params, index, maxage) {
|
|
2181
|
-
if (maxage <= 0) return false;
|
|
2182
|
-
if (params == null) return false;
|
|
2183
|
-
let c = this.cache[index.toString()];
|
|
2184
|
-
if (!c) {
|
|
2185
|
-
return false;
|
|
2186
|
-
}
|
|
2187
|
-
if (!Array.isArray(params)) params = [params];
|
|
2188
|
-
const rv = params.every(p => {
|
|
2189
|
-
p = this._toNamed(p);
|
|
2190
|
-
return (p in c) && (Date.now() - c[p].ctime <= maxage);
|
|
2191
|
-
});
|
|
2192
|
-
return rv;
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
|
-
_getCache(params, index) {
|
|
2196
|
-
let c = this.cache[index.toString()];
|
|
2197
|
-
if (!c) return null;
|
|
2198
|
-
if (!Array.isArray(params)){
|
|
2199
|
-
if (params in c) return c[params].value;
|
|
2200
|
-
return null;
|
|
2201
|
-
}else {
|
|
2202
|
-
return params.map(p => p in c ? c[p].value : null);
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
|
|
2206
|
-
_toNamed(param) {
|
|
2207
|
-
const idx = param.lastIndexOf('.');
|
|
2208
|
-
if (idx < 0) return param;
|
|
2209
|
-
else return param.slice(idx+1);
|
|
2210
|
-
}
|
|
2211
|
-
|
|
2212
|
-
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
class CachingGateway extends Gateway{
|
|
2216
|
-
|
|
2217
|
-
/**
|
|
2218
|
-
* Get an AgentID for a given agent name.
|
|
2219
|
-
*
|
|
2220
|
-
* @param {string} name - name of agent
|
|
2221
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2222
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2223
|
-
* @returns {AgentID|CachingAgentID} - AgentID for the given name
|
|
2224
|
-
*/
|
|
2225
|
-
agent(name, caching=true, greedy=true) {
|
|
2226
|
-
const aid = super.agent(name);
|
|
2227
|
-
return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
|
|
2228
|
-
}
|
|
2229
|
-
|
|
2230
|
-
/**
|
|
2231
|
-
* Returns an object representing the named topic.
|
|
2232
|
-
*
|
|
2233
|
-
* @param {string|AgentID} topic - name of the topic or AgentID
|
|
2234
|
-
* @param {string} topic2 - name of the topic if the topic param is an AgentID
|
|
2235
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2236
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2237
|
-
* @returns {AgentID|CachingAgentID} - object representing the topic
|
|
2238
|
-
*/
|
|
2239
|
-
topic(topic, topic2, caching=true, greedy=true) {
|
|
2240
|
-
const aid = super.topic(topic, topic2);
|
|
2241
|
-
return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
|
-
/**
|
|
2245
|
-
* Finds an agent that provides a named service. If multiple agents are registered
|
|
2246
|
-
* to provide a given service, any of the agents' id may be returned.
|
|
2247
|
-
*
|
|
2248
|
-
* @param {string} service - the named service of interest
|
|
2249
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2250
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2251
|
-
* @returns {Promise<?AgentID|CachingAgentID>} - a promise which returns an agent id for an agent that provides the service when resolved
|
|
2252
|
-
*/
|
|
2253
|
-
async agentForService(service, caching=true, greedy=true) {
|
|
2254
|
-
const aid = await super.agentForService(service);
|
|
2255
|
-
if (!aid) return aid;
|
|
2256
|
-
return caching ? new CachingAgentID(aid, null, null, greedy) : aid;
|
|
2257
|
-
}
|
|
2258
|
-
|
|
2259
|
-
/**
|
|
2260
|
-
* Finds all agents that provides a named service.
|
|
2261
|
-
*
|
|
2262
|
-
* @param {string} service - the named service of interest
|
|
2263
|
-
* @param {Boolean} [caching=true] - if the AgentID should cache parameters
|
|
2264
|
-
* @param {Boolean} [greedy=true] - greedily fetches and caches all parameters if this Agent
|
|
2265
|
-
* @returns {Promise<?AgentID|CachingAgentID[]>} - a promise which returns an array of all agent ids that provides the service when resolved
|
|
2266
|
-
*/
|
|
2267
|
-
async agentsForService(service, caching=true, greedy=true) {
|
|
2268
|
-
const aids = await super.agentsForService(service);
|
|
2269
|
-
return caching ? aids.map(a => new CachingAgentID(a, null, null, greedy)) : aids;
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
|
|
2112
|
+
const BROADCAST_ADDR = 0;
|
|
2273
2113
|
const REQUEST_TIMEOUT = 1000;
|
|
2114
|
+
const NON_BLOCKING = 0;
|
|
2115
|
+
const SEMI_BLOCKING = 1;
|
|
2116
|
+
const BLOCKING = 2;
|
|
2274
2117
|
|
|
2275
2118
|
const AddressResolutionReq = UnetMessages.AddressResolutionReq;
|
|
2119
|
+
const DatagramDeliveryNtf = UnetMessages.DatagramDeliveryNtf;
|
|
2120
|
+
const DatagramFailureNtf = UnetMessages.DatagramFailureNtf;
|
|
2276
2121
|
const DatagramReq = UnetMessages.DatagramReq;
|
|
2277
2122
|
const DatagramNtf = UnetMessages.DatagramNtf;
|
|
2278
|
-
const
|
|
2123
|
+
const DatagramTransmissionNtf = UnetMessages.DatagramTransmissionNtf;
|
|
2124
|
+
const RemoteDeliveryNtf = UnetMessages.RemoteDeliveryNtf;
|
|
2125
|
+
const RemoteFailureNtf = UnetMessages.RemoteFailureNtf;
|
|
2126
|
+
const RemoteSuccessNtf = UnetMessages.RemoteSuccessNtf;
|
|
2127
|
+
|
|
2128
|
+
function isReservedProtocol(protocol) {
|
|
2129
|
+
return protocol != Protocol.DATA && (protocol < Protocol.USER || protocol > Protocol.MAX);
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
function hasValue(value) {
|
|
2133
|
+
return value !== undefined && value !== null;
|
|
2134
|
+
}
|
|
2279
2135
|
|
|
2136
|
+
function hasFiniteNumber(value) {
|
|
2137
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
2138
|
+
}
|
|
2280
2139
|
/**
|
|
2281
2140
|
* Creates a new UnetSocket to connect to a running Unet instance. This constructor returns a
|
|
2282
2141
|
* {@link Promise} instead of the constructed UnetSocket object. Use `await` or `.then()` to get
|
|
@@ -2297,18 +2156,63 @@ class UnetSocket {
|
|
|
2297
2156
|
|
|
2298
2157
|
constructor(hostname, port, path='') {
|
|
2299
2158
|
return (async () => {
|
|
2300
|
-
this.
|
|
2159
|
+
this._gw = new Gateway({
|
|
2301
2160
|
hostname : hostname,
|
|
2302
2161
|
port : port,
|
|
2303
2162
|
path : path
|
|
2304
2163
|
});
|
|
2305
|
-
this.
|
|
2306
|
-
this.
|
|
2307
|
-
this.
|
|
2308
|
-
this.
|
|
2309
|
-
this.
|
|
2310
|
-
|
|
2311
|
-
|
|
2164
|
+
this._localProtocol = -1;
|
|
2165
|
+
this._remoteAddress = -1;
|
|
2166
|
+
this._localAddress = -1;
|
|
2167
|
+
this._remoteProtocol = Protocol.DATA;
|
|
2168
|
+
this._timeout = 0;
|
|
2169
|
+
this._serviceProvider = null;
|
|
2170
|
+
this._ttl = NaN;
|
|
2171
|
+
this._priority = null;
|
|
2172
|
+
this._reliability = null;
|
|
2173
|
+
this._route = null;
|
|
2174
|
+
this._mimeType = null;
|
|
2175
|
+
this._remoteRecipient = null;
|
|
2176
|
+
this._mailbox = null;
|
|
2177
|
+
this._messageClass = null;
|
|
2178
|
+
this._sendMode = SEMI_BLOCKING;
|
|
2179
|
+
this._warnedDeprecatedSend = false;
|
|
2180
|
+
this._paramChangeCallbacks = {};
|
|
2181
|
+
|
|
2182
|
+
//for new UnetStack versions (5.2.0 and later)
|
|
2183
|
+
this._gw.subscribe(this._gw.topic(UnetTopics.DATAGRAM));
|
|
2184
|
+
|
|
2185
|
+
//for compatibility with older UnetStack versions (before 5.2.0)
|
|
2186
|
+
const alist = await this._gw.agentsForService(Services.DATAGRAM);
|
|
2187
|
+
alist.forEach(a => {this._gw.subscribe(this._gw.topic(a));});
|
|
2188
|
+
|
|
2189
|
+
// get local nodeinfo agent
|
|
2190
|
+
const nodeinfo = await this._gw.agentForService(Services.NODE_INFO);
|
|
2191
|
+
|
|
2192
|
+
// subscribe to paramchange notifications for onParamChange callbacks
|
|
2193
|
+
this._gw.subscribe(this._gw.topic(UnetTopics.PARAMCHANGE));
|
|
2194
|
+
if (nodeinfo != null) this._gw.subscribe(this._gw.topic(nodeinfo)); // nodeinfo publishes param changes for local node parameters
|
|
2195
|
+
this._gw.addMessageListener(msg => {
|
|
2196
|
+
if (msg instanceof UnetMessages.ParamChangeNtf) {
|
|
2197
|
+
const sender = (msg.sender instanceof AgentID) ? msg.sender.name : msg.sender;
|
|
2198
|
+
if (msg.paramValues != null){
|
|
2199
|
+
for (const p in msg.paramValues) {
|
|
2200
|
+
// if p has dots inside then take the substring after the last dot as the parameter name,
|
|
2201
|
+
// since many times fully qualified parameter names are used in the notifications
|
|
2202
|
+
const paramName = p.includes('.') ? p.substring(p.lastIndexOf('.') + 1) : p;
|
|
2203
|
+
const callback = this._paramChangeCallbacks[sender + '.' + paramName];
|
|
2204
|
+
if (callback != null) callback(msg.paramValues[p]);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
2209
|
+
|
|
2210
|
+
// get local node address and subscribe to changes in the local node address
|
|
2211
|
+
if (nodeinfo != null) {
|
|
2212
|
+
this.onParamChange(nodeinfo.name, 'address', (addr) => { this._localAddress = addr; });
|
|
2213
|
+
this._localAddress = await nodeinfo.get('address');
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2312
2216
|
return this;
|
|
2313
2217
|
})();
|
|
2314
2218
|
}
|
|
@@ -2318,8 +2222,8 @@ class UnetSocket {
|
|
|
2318
2222
|
* @returns {void}
|
|
2319
2223
|
*/
|
|
2320
2224
|
close() {
|
|
2321
|
-
this.
|
|
2322
|
-
this.
|
|
2225
|
+
this._gw.close();
|
|
2226
|
+
this._gw = null;
|
|
2323
2227
|
}
|
|
2324
2228
|
|
|
2325
2229
|
/**
|
|
@@ -2327,7 +2231,7 @@ class UnetSocket {
|
|
|
2327
2231
|
* @returns {boolean} - true if closed, false if open
|
|
2328
2232
|
*/
|
|
2329
2233
|
isClosed() {
|
|
2330
|
-
return this.
|
|
2234
|
+
return this._gw == null;
|
|
2331
2235
|
}
|
|
2332
2236
|
|
|
2333
2237
|
/**
|
|
@@ -2339,7 +2243,7 @@ class UnetSocket {
|
|
|
2339
2243
|
*/
|
|
2340
2244
|
bind(protocol) {
|
|
2341
2245
|
if (protocol == Protocol.DATA || (protocol >= Protocol.USER && protocol <= Protocol.MAX)) {
|
|
2342
|
-
this.
|
|
2246
|
+
this._localProtocol = protocol;
|
|
2343
2247
|
return true;
|
|
2344
2248
|
}
|
|
2345
2249
|
return false;
|
|
@@ -2350,13 +2254,13 @@ class UnetSocket {
|
|
|
2350
2254
|
* Protocol numbers between Protocol.DATA+1 to Protocol.USER-1 are considered reserved.
|
|
2351
2255
|
* @returns {void}
|
|
2352
2256
|
*/
|
|
2353
|
-
unbind() { this.
|
|
2257
|
+
unbind() { this._localProtocol = -1;}
|
|
2354
2258
|
|
|
2355
2259
|
/**
|
|
2356
2260
|
* Checks if a socket is bound.
|
|
2357
2261
|
* @returns {boolean} - true if bound to a protocol, false if unbound
|
|
2358
2262
|
*/
|
|
2359
|
-
isBound() { return this.
|
|
2263
|
+
isBound() { return this._localProtocol >= 0;}
|
|
2360
2264
|
|
|
2361
2265
|
/**
|
|
2362
2266
|
* Sets the default destination address and destination protocol number for datagrams sent
|
|
@@ -2372,8 +2276,8 @@ class UnetSocket {
|
|
|
2372
2276
|
*/
|
|
2373
2277
|
connect(to, protocol) {
|
|
2374
2278
|
if (to >= 0 && (protocol == Protocol.DATA || (protocol >= Protocol.USER && protocol <= Protocol.MAX))) {
|
|
2375
|
-
this.
|
|
2376
|
-
this.
|
|
2279
|
+
this._remoteAddress = to;
|
|
2280
|
+
this._remoteProtocol = protocol;
|
|
2377
2281
|
return true;
|
|
2378
2282
|
}
|
|
2379
2283
|
return false;
|
|
@@ -2385,23 +2289,23 @@ class UnetSocket {
|
|
|
2385
2289
|
* @returns {void}
|
|
2386
2290
|
*/
|
|
2387
2291
|
disconnect() {
|
|
2388
|
-
this.
|
|
2389
|
-
this.
|
|
2292
|
+
this._remoteAddress = -1;
|
|
2293
|
+
this._remoteProtocol = 0;
|
|
2390
2294
|
}
|
|
2391
2295
|
|
|
2392
2296
|
/**
|
|
2393
2297
|
* Checks if a socket is connected, i.e., has a default destination address and protocol number.
|
|
2394
2298
|
* @returns {boolean} - true if connected, false otherwise
|
|
2395
2299
|
*/
|
|
2396
|
-
isConnected() { return this.
|
|
2300
|
+
isConnected() { return this._remoteAddress >= 0; }
|
|
2397
2301
|
|
|
2398
2302
|
/**
|
|
2399
2303
|
* Gets the local node address of the Unet node connected to.
|
|
2400
2304
|
* @returns {Promise<int>} - local node address, or -1 on error
|
|
2401
2305
|
*/
|
|
2402
2306
|
async getLocalAddress() {
|
|
2403
|
-
if (this.
|
|
2404
|
-
const nodeinfo = await this.
|
|
2307
|
+
if (this._gw == null) return -1;
|
|
2308
|
+
const nodeinfo = await this._gw.agentForService(Services.NODE_INFO);
|
|
2405
2309
|
if (nodeinfo == null) return -1;
|
|
2406
2310
|
const addr = await nodeinfo.get('address');
|
|
2407
2311
|
return addr != null ? addr : -1;
|
|
@@ -2409,21 +2313,21 @@ class UnetSocket {
|
|
|
2409
2313
|
|
|
2410
2314
|
/**
|
|
2411
2315
|
* Gets the protocol number that the socket is bound to.
|
|
2412
|
-
* @returns {number}
|
|
2316
|
+
* @returns {number} - protocol number if socket is bound, -1 otherwise
|
|
2413
2317
|
*/
|
|
2414
|
-
getLocalProtocol() { return this.
|
|
2318
|
+
getLocalProtocol() { return this._localProtocol; }
|
|
2415
2319
|
|
|
2416
2320
|
/**
|
|
2417
2321
|
* Gets the default destination node address for a connected socket.
|
|
2418
|
-
* @returns {number}
|
|
2322
|
+
* @returns {number} - default destination node address if connected, -1 otherwise
|
|
2419
2323
|
*/
|
|
2420
|
-
getRemoteAddress() { return this.
|
|
2324
|
+
getRemoteAddress() { return this._remoteAddress; }
|
|
2421
2325
|
|
|
2422
2326
|
/**
|
|
2423
2327
|
* Gets the default transmission protocol number.
|
|
2424
|
-
* @returns {number}
|
|
2328
|
+
* @returns {number} - default protocol number used to transmit a datagram
|
|
2425
2329
|
*/
|
|
2426
|
-
getRemoteProtocol() { return this.
|
|
2330
|
+
getRemoteProtocol() { return this._remoteProtocol; }
|
|
2427
2331
|
|
|
2428
2332
|
/**
|
|
2429
2333
|
* Sets the timeout for datagram reception. A timeout of 0 means the
|
|
@@ -2435,14 +2339,275 @@ class UnetSocket {
|
|
|
2435
2339
|
*/
|
|
2436
2340
|
setTimeout(ms) {
|
|
2437
2341
|
if (ms < 0) ms = 0;
|
|
2438
|
-
this.
|
|
2342
|
+
this._timeout = ms;
|
|
2439
2343
|
}
|
|
2440
2344
|
|
|
2441
2345
|
/**
|
|
2442
2346
|
* Gets the timeout for datagram reception.
|
|
2443
2347
|
* @returns {number} - timeout in milliseconds
|
|
2444
2348
|
*/
|
|
2445
|
-
getTimeout() { return this.
|
|
2349
|
+
getTimeout() { return this._timeout; }
|
|
2350
|
+
|
|
2351
|
+
/**
|
|
2352
|
+
* Sets the default time-to-live for datagrams sent using this socket.
|
|
2353
|
+
* TTL is advisory; an agent may choose to ignore it.
|
|
2354
|
+
* @param {number} ttl - time-to-live in seconds
|
|
2355
|
+
* @returns {void}
|
|
2356
|
+
*/
|
|
2357
|
+
setTTL(ttl) {
|
|
2358
|
+
this._ttl = ttl;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
/**
|
|
2362
|
+
* Gets the default time-to-live for datagrams sent using this socket.
|
|
2363
|
+
* @returns {number} - time-to-live in seconds, or NaN if not set
|
|
2364
|
+
*/
|
|
2365
|
+
getTTL() {
|
|
2366
|
+
return this._ttl;
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
/**
|
|
2370
|
+
* Sets the default priority for datagrams sent using this socket.
|
|
2371
|
+
* @param {*} priority - priority value; interpretation is provider-dependent
|
|
2372
|
+
* @returns {void}
|
|
2373
|
+
*/
|
|
2374
|
+
setPriority(priority) {
|
|
2375
|
+
this._priority = priority;
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
/**
|
|
2379
|
+
* Gets the default priority for datagrams sent using this socket.
|
|
2380
|
+
* @returns {*} - priority value, or null if not set
|
|
2381
|
+
*/
|
|
2382
|
+
getPriority() {
|
|
2383
|
+
return this._priority;
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
/**
|
|
2387
|
+
* Sets the default reliability for datagrams sent using this socket.
|
|
2388
|
+
* When set to true, the socket will request reliable delivery and, in
|
|
2389
|
+
* SEMI_BLOCKING mode, will wait for a delivery confirmation before returning.
|
|
2390
|
+
* @param {boolean} reliability - true for reliable delivery, false for unreliable
|
|
2391
|
+
* @returns {void}
|
|
2392
|
+
*/
|
|
2393
|
+
setReliability(reliability) {
|
|
2394
|
+
this._reliability = reliability;
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2397
|
+
/**
|
|
2398
|
+
* Gets the default reliability setting for datagrams sent using this socket.
|
|
2399
|
+
* @returns {boolean|null} - true if reliable, false if unreliable, null if not set
|
|
2400
|
+
*/
|
|
2401
|
+
getReliability() {
|
|
2402
|
+
return this._reliability;
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
/**
|
|
2406
|
+
* Sets the default route identifier for datagrams sent using this socket.
|
|
2407
|
+
* Route selection is provider-dependent; not all providers support explicit routing.
|
|
2408
|
+
* @param {*} route - route identifier
|
|
2409
|
+
* @returns {void}
|
|
2410
|
+
*/
|
|
2411
|
+
setRoute(route) {
|
|
2412
|
+
this._route = route;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
* Gets the default route identifier for datagrams sent using this socket.
|
|
2417
|
+
* @returns {*} - route identifier, or null if not set
|
|
2418
|
+
*/
|
|
2419
|
+
getRoute() {
|
|
2420
|
+
return this._route;
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
/**
|
|
2424
|
+
* Sets the default MIME type describing the datagram payload.
|
|
2425
|
+
* This can be used by REMOTE service providers to apply content-aware compression.
|
|
2426
|
+
* @param {string} mimeType - MIME type string (e.g. 'application/json')
|
|
2427
|
+
* @returns {void}
|
|
2428
|
+
*/
|
|
2429
|
+
setMimeType(mimeType) {
|
|
2430
|
+
this._mimeType = mimeType;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
/**
|
|
2434
|
+
* Gets the default MIME type for datagrams sent using this socket.
|
|
2435
|
+
* @returns {string|null} - MIME type string, or null if not set
|
|
2436
|
+
*/
|
|
2437
|
+
getMimeType() {
|
|
2438
|
+
return this._mimeType;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
/**
|
|
2442
|
+
* Sets the default remote recipient for datagrams sent using this socket.
|
|
2443
|
+
* Used by REMOTE service providers to address a specific entity on the remote node.
|
|
2444
|
+
* @param {*} remoteRecipient - remote recipient identifier (e.g. an AgentID or name string)
|
|
2445
|
+
* @returns {void}
|
|
2446
|
+
*/
|
|
2447
|
+
setRemoteRecipient(remoteRecipient) {
|
|
2448
|
+
this._remoteRecipient = remoteRecipient;
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
/**
|
|
2452
|
+
* Gets the default remote recipient for datagrams sent using this socket.
|
|
2453
|
+
* @returns {*} - remote recipient identifier, or null if not set
|
|
2454
|
+
*/
|
|
2455
|
+
getRemoteRecipient() {
|
|
2456
|
+
return this._remoteRecipient;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
/**
|
|
2460
|
+
* Sets the default mailbox name for datagrams sent using this socket.
|
|
2461
|
+
* Mailboxes are used by REMOTE service providers to deliver messages
|
|
2462
|
+
* to a named queue on the remote node.
|
|
2463
|
+
* @param {string} mailbox - mailbox name
|
|
2464
|
+
* @returns {void}
|
|
2465
|
+
*/
|
|
2466
|
+
setMailbox(mailbox) {
|
|
2467
|
+
this._mailbox = mailbox;
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
/**
|
|
2471
|
+
* Gets the default mailbox name for datagrams sent using this socket.
|
|
2472
|
+
* @returns {string|null} - mailbox name, or null if not set
|
|
2473
|
+
*/
|
|
2474
|
+
getMailbox() {
|
|
2475
|
+
return this._mailbox;
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
/**
|
|
2479
|
+
* Sets the default application message class for datagrams sent using this socket.
|
|
2480
|
+
* Used by REMOTE service providers to associate a fully-qualified class name with the payload.
|
|
2481
|
+
* @param {string} messageClass - fully-qualified message class name (e.g. 'org.example.Status')
|
|
2482
|
+
* @returns {void}
|
|
2483
|
+
*/
|
|
2484
|
+
setMessageClass(messageClass) {
|
|
2485
|
+
this._messageClass = messageClass;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
/**
|
|
2489
|
+
* Gets the default application message class for datagrams sent using this socket.
|
|
2490
|
+
* @returns {string|null} - message class name, or null if not set
|
|
2491
|
+
*/
|
|
2492
|
+
getMessageClass() {
|
|
2493
|
+
return this._messageClass;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
/**
|
|
2497
|
+
* Overrides the service provider used to transmit datagrams. When set, provider
|
|
2498
|
+
* auto-selection is bypassed and all sends go through the specified agent.
|
|
2499
|
+
* Pass null to re-enable auto-selection.
|
|
2500
|
+
* @param {AgentID|string|null} provider - agent id, agent name string, or null to clear the override
|
|
2501
|
+
* @returns {void}
|
|
2502
|
+
*/
|
|
2503
|
+
setServiceProvider(provider) {
|
|
2504
|
+
if (typeof provider === 'string') provider = this.agent(provider);
|
|
2505
|
+
this._serviceProvider = provider instanceof AgentID || provider == null ? provider : null;
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
/**
|
|
2509
|
+
* Gets the currently configured service provider override.
|
|
2510
|
+
* @returns {AgentID|null} - the override agent id, or null if auto-selection is active
|
|
2511
|
+
*/
|
|
2512
|
+
getServiceProvider() {
|
|
2513
|
+
return this._serviceProvider;
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
/**
|
|
2517
|
+
* Sets the send mode that controls how send() behaves after the provider accepts a request:
|
|
2518
|
+
* - `UnetSocket.NON_BLOCKING` (0): returns immediately after the provider agrees.
|
|
2519
|
+
* - `UnetSocket.SEMI_BLOCKING` (1): if reliability is not true, returns after AGREE; otherwise
|
|
2520
|
+
* waits for a delivery confirmation (RemoteDeliveryNtf / DatagramDeliveryNtf) or failure.
|
|
2521
|
+
* - `UnetSocket.BLOCKING` (2): waits for a transmission or delivery notification
|
|
2522
|
+
* (DatagramTransmissionNtf, DatagramDeliveryNtf) before returning.
|
|
2523
|
+
* The default is SEMI_BLOCKING.
|
|
2524
|
+
* @param {number} sendMode - one of UnetSocket.NON_BLOCKING, SEMI_BLOCKING, or BLOCKING
|
|
2525
|
+
* @returns {void}
|
|
2526
|
+
*/
|
|
2527
|
+
setSendMode(sendMode) {
|
|
2528
|
+
if ([NON_BLOCKING, SEMI_BLOCKING, BLOCKING].includes(sendMode)) this._sendMode = sendMode;
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
/**
|
|
2532
|
+
* Gets the current send mode.
|
|
2533
|
+
* @returns {number} - current send mode (NON_BLOCKING=0, SEMI_BLOCKING=1, BLOCKING=2)
|
|
2534
|
+
*/
|
|
2535
|
+
getSendMode() {
|
|
2536
|
+
return this._sendMode;
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
async _chooseAgentForService(service) {
|
|
2540
|
+
const agents = await this._gw.agentsForService(service);
|
|
2541
|
+
if (agents == null || agents.length === 0) return null;
|
|
2542
|
+
return agents[Math.floor(Math.random() * agents.length)];
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
async _resolveProvider() {
|
|
2546
|
+
if (this._serviceProvider != null) return this._serviceProvider;
|
|
2547
|
+
const serviceOrder = [
|
|
2548
|
+
Services.REMOTE,
|
|
2549
|
+
Services.TRANSPORT,
|
|
2550
|
+
Services.ROUTING,
|
|
2551
|
+
Services.LINK,
|
|
2552
|
+
Services.PHYSICAL,
|
|
2553
|
+
Services.DATAGRAM,
|
|
2554
|
+
];
|
|
2555
|
+
for (const service of serviceOrder) {
|
|
2556
|
+
const provider = await this._chooseAgentForService(service);
|
|
2557
|
+
if (provider != null) return provider;
|
|
2558
|
+
}
|
|
2559
|
+
return null;
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
_applySocketSettings(req) {
|
|
2563
|
+
if (!hasValue(req.priority) && hasValue(this._priority)) req.priority = this._priority;
|
|
2564
|
+
if (!hasValue(req.reliability) && hasValue(this._reliability)) req.reliability = this._reliability;
|
|
2565
|
+
if ((!hasValue(req.ttl) || Number.isNaN(req.ttl)) && hasFiniteNumber(this._ttl)) req.ttl = this._ttl;
|
|
2566
|
+
if (!hasValue(req.route) && hasValue(this._route)) req.route = this._route;
|
|
2567
|
+
if (!hasValue(req.mimeType) && hasValue(this._mimeType)) req.mimeType = this._mimeType;
|
|
2568
|
+
if (!hasValue(req.remoteRecipient) && hasValue(this._remoteRecipient)) req.remoteRecipient = this._remoteRecipient;
|
|
2569
|
+
if (!hasValue(req.mailbox) && hasValue(this._mailbox)) req.mailbox = this._mailbox;
|
|
2570
|
+
if (!hasValue(req.messageClass) && hasValue(this._messageClass)) req.messageClass = this._messageClass;
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
_effectiveReliability(req) {
|
|
2574
|
+
return hasValue(req.reliability) ? req.reliability : this._reliability;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
async _waitForNotification(req, types, timeout = REQUEST_TIMEOUT) {
|
|
2578
|
+
return await this._gw.receive(msg => {
|
|
2579
|
+
if (!types.some(type => msg instanceof type)) return false;
|
|
2580
|
+
if (hasValue(msg.inReplyTo) && msg.inReplyTo === req.msgID) return true;
|
|
2581
|
+
return false;
|
|
2582
|
+
}, timeout);
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
async _waitForSemiBlockingOutcome(req) {
|
|
2586
|
+
const notification = await this._waitForNotification(req, [
|
|
2587
|
+
DatagramDeliveryNtf,
|
|
2588
|
+
DatagramFailureNtf,
|
|
2589
|
+
RemoteDeliveryNtf,
|
|
2590
|
+
RemoteSuccessNtf,
|
|
2591
|
+
RemoteFailureNtf,
|
|
2592
|
+
]);
|
|
2593
|
+
if (notification == null) return false;
|
|
2594
|
+
if (notification instanceof DatagramFailureNtf || notification instanceof RemoteFailureNtf) return false;
|
|
2595
|
+
return true;
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
async _waitForBlockingOutcome(req) {
|
|
2599
|
+
const notification = await this._waitForNotification(req, [
|
|
2600
|
+
DatagramTransmissionNtf,
|
|
2601
|
+
DatagramDeliveryNtf,
|
|
2602
|
+
DatagramFailureNtf,
|
|
2603
|
+
RemoteDeliveryNtf,
|
|
2604
|
+
RemoteSuccessNtf,
|
|
2605
|
+
RemoteFailureNtf,
|
|
2606
|
+
]);
|
|
2607
|
+
if (notification == null) return false;
|
|
2608
|
+
if (notification instanceof DatagramFailureNtf || notification instanceof RemoteFailureNtf) return false;
|
|
2609
|
+
return true;
|
|
2610
|
+
}
|
|
2446
2611
|
|
|
2447
2612
|
/**
|
|
2448
2613
|
* Transmits a datagram to the specified node address using the specified protocol.
|
|
@@ -2453,32 +2618,43 @@ class UnetSocket {
|
|
|
2453
2618
|
* @param {number} protocol - protocol number
|
|
2454
2619
|
* @returns {Promise<boolean>} - true if the Unet node agreed to send out the Datagram, false otherwise
|
|
2455
2620
|
*/
|
|
2456
|
-
async send(data, to=this.
|
|
2457
|
-
if (
|
|
2458
|
-
|
|
2459
|
-
if (Array.isArray(data)){
|
|
2621
|
+
async send(data, to=this._remoteAddress, protocol=this._remoteProtocol) {
|
|
2622
|
+
if (this._gw == null) return false;
|
|
2623
|
+
let req;
|
|
2624
|
+
if (Array.isArray(data)) {
|
|
2460
2625
|
req = new DatagramReq();
|
|
2461
2626
|
req.data = data;
|
|
2462
2627
|
req.to = to;
|
|
2463
2628
|
req.protocol = protocol;
|
|
2464
|
-
} else if (data instanceof DatagramReq){
|
|
2629
|
+
} else if (data instanceof DatagramReq) {
|
|
2465
2630
|
req = data;
|
|
2631
|
+
if (!this._warnedDeprecatedSend && typeof console !== 'undefined' && typeof console.warn === 'function') {
|
|
2632
|
+
console.warn('UnetSocket.send(DatagramReq) is deprecated; prefer socket metadata setters with send(data, to, protocol).');
|
|
2633
|
+
this._warnedDeprecatedSend = true;
|
|
2634
|
+
}
|
|
2466
2635
|
} else {
|
|
2467
2636
|
return false;
|
|
2468
2637
|
}
|
|
2469
|
-
|
|
2470
|
-
if (
|
|
2638
|
+
if ((!hasValue(req.to) || req.to < 0) && to >= 0) req.to = to;
|
|
2639
|
+
if (!hasValue(req.protocol)) req.protocol = protocol;
|
|
2640
|
+
this._applySocketSettings(req);
|
|
2641
|
+
|
|
2642
|
+
if (!Array.isArray(req.data) || req.to < 0 || isReservedProtocol(req.protocol)) return false;
|
|
2471
2643
|
if (req.recipient == null) {
|
|
2472
|
-
|
|
2473
|
-
if (
|
|
2474
|
-
if (this.provider == null) this.provider = await this.gw.agentForService(Services.LINK);
|
|
2475
|
-
if (this.provider == null) this.provider = await this.gw.agentForService(Services.PHYSICAL);
|
|
2476
|
-
if (this.provider == null) this.provider = await this.gw.agentForService(Services.DATAGRAM);
|
|
2477
|
-
if (this.provider == null) return false;
|
|
2478
|
-
req.recipient = this.provider;
|
|
2644
|
+
req.recipient = await this._resolveProvider();
|
|
2645
|
+
if (req.recipient == null) return false;
|
|
2479
2646
|
}
|
|
2480
|
-
const rsp = await this.
|
|
2481
|
-
|
|
2647
|
+
const rsp = await this._gw.request(req, REQUEST_TIMEOUT);
|
|
2648
|
+
if (rsp == null || rsp.perf != Performative.AGREE) return false;
|
|
2649
|
+
|
|
2650
|
+
if (this._sendMode === NON_BLOCKING) return true;
|
|
2651
|
+
|
|
2652
|
+
if (this._sendMode === SEMI_BLOCKING) {
|
|
2653
|
+
if (this._effectiveReliability(req) !== true) return true;
|
|
2654
|
+
return await this._waitForSemiBlockingOutcome(req);
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
return await this._waitForBlockingOutcome(req);
|
|
2482
2658
|
}
|
|
2483
2659
|
|
|
2484
2660
|
/**
|
|
@@ -2488,22 +2664,23 @@ class UnetSocket {
|
|
|
2488
2664
|
* @returns {Promise<?DatagramNtf>} - datagram received by the socket
|
|
2489
2665
|
*/
|
|
2490
2666
|
async receive() {
|
|
2491
|
-
if (this.
|
|
2492
|
-
return await this.
|
|
2493
|
-
if (msg
|
|
2667
|
+
if (this._gw == null) return null;
|
|
2668
|
+
return await this._gw.receive(msg => {
|
|
2669
|
+
if (!(msg instanceof DatagramNtf)) return false;
|
|
2494
2670
|
let p = msg.protocol;
|
|
2671
|
+
if (msg.to != BROADCAST_ADDR && msg.to != this._localAddress) return false; // Datagram not addressed to this node
|
|
2495
2672
|
if (p == Protocol.DATA || p >= Protocol.USER) {
|
|
2496
|
-
return this.
|
|
2673
|
+
return this._localProtocol < 0 || this._localProtocol == p;
|
|
2497
2674
|
}
|
|
2498
2675
|
return false;
|
|
2499
|
-
}, this.
|
|
2676
|
+
}, this._timeout);
|
|
2500
2677
|
}
|
|
2501
2678
|
|
|
2502
2679
|
/**
|
|
2503
2680
|
* Gets a Gateway to provide low-level access to UnetStack.
|
|
2504
2681
|
* @returns {Gateway} - underlying fjage Gateway supporting this socket
|
|
2505
2682
|
*/
|
|
2506
|
-
getGateway() { return this.
|
|
2683
|
+
getGateway() { return this._gw; }
|
|
2507
2684
|
|
|
2508
2685
|
/**
|
|
2509
2686
|
* Gets an AgentID providing a specified service for low-level access to UnetStack
|
|
@@ -2511,8 +2688,8 @@ class UnetSocket {
|
|
|
2511
2688
|
* @returns {Promise<?AgentID>} - a promise which returns an {@link AgentID} that provides the service when resolved
|
|
2512
2689
|
*/
|
|
2513
2690
|
async agentForService(svc) {
|
|
2514
|
-
if (this.
|
|
2515
|
-
return await this.
|
|
2691
|
+
if (this._gw == null) return null;
|
|
2692
|
+
return await this._gw.agentForService(svc);
|
|
2516
2693
|
}
|
|
2517
2694
|
|
|
2518
2695
|
/**
|
|
@@ -2521,8 +2698,8 @@ class UnetSocket {
|
|
|
2521
2698
|
* @returns {Promise<AgentID[]>} - a promise which returns an array of {@link AgentID|AgentIDs} that provides the service when resolved
|
|
2522
2699
|
*/
|
|
2523
2700
|
async agentsForService(svc) {
|
|
2524
|
-
if (this.
|
|
2525
|
-
return await this.
|
|
2701
|
+
if (this._gw == null) return null;
|
|
2702
|
+
return await this._gw.agentsForService(svc);
|
|
2526
2703
|
}
|
|
2527
2704
|
|
|
2528
2705
|
/**
|
|
@@ -2531,8 +2708,8 @@ class UnetSocket {
|
|
|
2531
2708
|
* @returns {AgentID} - AgentID for the given name
|
|
2532
2709
|
*/
|
|
2533
2710
|
agent(name) {
|
|
2534
|
-
if (this.
|
|
2535
|
-
return this.
|
|
2711
|
+
if (this._gw == null) return null;
|
|
2712
|
+
return this._gw.agent(name);
|
|
2536
2713
|
}
|
|
2537
2714
|
|
|
2538
2715
|
/**
|
|
@@ -2546,15 +2723,42 @@ class UnetSocket {
|
|
|
2546
2723
|
const req = new AddressResolutionReq(nodeName);
|
|
2547
2724
|
req.name = nodeName;
|
|
2548
2725
|
req.recipient = arp;
|
|
2549
|
-
const rsp = await this.
|
|
2726
|
+
const rsp = await this._gw.request(req, REQUEST_TIMEOUT);
|
|
2550
2727
|
if (rsp == null || ! Object.prototype.hasOwnProperty.call(rsp, 'address')) return null;
|
|
2551
2728
|
return rsp.address;
|
|
2552
2729
|
}
|
|
2730
|
+
|
|
2731
|
+
/**
|
|
2732
|
+
* Registers a callback function to be called when a parameter value changes for the local node. This
|
|
2733
|
+
* uses the ParamChangeNtf messages published by the Unet node to notify of parameter changes. The callback
|
|
2734
|
+
* function will be called with the new value of the parameter.
|
|
2735
|
+
*
|
|
2736
|
+
* @param {AgentID|string} agentId
|
|
2737
|
+
* @param {string} paramName
|
|
2738
|
+
* @param {function(object): void} callback
|
|
2739
|
+
*/
|
|
2740
|
+
onParamChange(agentId, paramName, callback) {
|
|
2741
|
+
if (agentId instanceof AgentID) agentId = agentId.name;
|
|
2742
|
+
this._paramChangeCallbacks[agentId + '.' + paramName] = callback;
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
/**
|
|
2746
|
+
* Removes a callback function registered to be called when a parameter value changes for the local node.
|
|
2747
|
+
*
|
|
2748
|
+
* @param {AgentID|string} agentId
|
|
2749
|
+
* @param {string} paramName
|
|
2750
|
+
*/
|
|
2751
|
+
removeParamChange(agentId, paramName) {
|
|
2752
|
+
if (agentId instanceof AgentID) agentId = agentId.name;
|
|
2753
|
+
delete this._paramChangeCallbacks[agentId + '.' + paramName];
|
|
2754
|
+
}
|
|
2553
2755
|
}
|
|
2554
2756
|
|
|
2757
|
+
UnetSocket.NON_BLOCKING = NON_BLOCKING;
|
|
2758
|
+
UnetSocket.SEMI_BLOCKING = SEMI_BLOCKING;
|
|
2759
|
+
UnetSocket.BLOCKING = BLOCKING;
|
|
2760
|
+
|
|
2555
2761
|
exports.AgentID = AgentID;
|
|
2556
|
-
exports.CachingAgentID = CachingAgentID;
|
|
2557
|
-
exports.CachingGateway = CachingGateway;
|
|
2558
2762
|
exports.Gateway = Gateway;
|
|
2559
2763
|
exports.Message = Message;
|
|
2560
2764
|
exports.MessageClass = MessageClass;
|
|
@@ -2563,5 +2767,6 @@ exports.Protocol = Protocol;
|
|
|
2563
2767
|
exports.Services = Services;
|
|
2564
2768
|
exports.UnetMessages = UnetMessages;
|
|
2565
2769
|
exports.UnetSocket = UnetSocket;
|
|
2770
|
+
exports.UnetTopics = UnetTopics;
|
|
2566
2771
|
exports.toGps = toGps;
|
|
2567
2772
|
exports.toLocal = toLocal;
|