4 rpcSessionID
= L
.env
.sessionid
|| '00000000000000000000000000000000',
5 rpcBaseURL
= L
.url('admin/ubus'),
6 rpcInterceptorFns
= [];
8 return L
.Class
.extend({
9 call: function(req
, cb
) {
12 if (Array
.isArray(req
)) {
14 return Promise
.resolve([]);
16 for (var i
= 0; i
< req
.length
; i
++)
17 q
+= '%s%s.%s'.format(
24 q
+= '/%s.%s'.format(req
.params
[1], req
.params
[2]);
27 return L
.Request
.post(rpcBaseURL
+ q
, req
, {
28 timeout
: (L
.env
.rpctimeout
|| 5) * 1000,
33 handleListReply: function(req
, msg
) {
34 var list
= msg
.result
;
36 /* verify message frame */
37 if (typeof(msg
) != 'object' || msg
.jsonrpc
!= '2.0' || !msg
.id
|| !Array
.isArray(list
))
43 parseCallReply: function(req
, res
) {
48 L
.raise('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
49 req
.object
, req
.method
, res
.status
, res
.statusText
|| '?');
58 * The interceptor args are intentionally swapped.
59 * Response is passed as first arg to align with Request class interceptors
61 Promise
.all(rpcInterceptorFns
.map(function(fn
) { return fn(msg
, req
) }))
62 .then(this.handleCallReply
.bind(this, req
, msg
))
66 handleCallReply: function(req
, msg
) {
67 var type
= Object
.prototype.toString
,
71 /* verify message frame */
72 if (!L
.isObject(msg
) || msg
.jsonrpc
!= '2.0')
73 L
.raise('RPCError', 'RPC call to %s/%s returned invalid message frame',
74 req
.object
, req
.method
);
76 /* check error condition */
77 if (L
.isObject(msg
.error
) && msg
.error
.code
&& msg
.error
.message
)
78 L
.raise('RPCError', 'RPC call to %s/%s failed with error %d: %s',
79 req
.object
, req
.method
, msg
.error
.code
, msg
.error
.message
|| '?');
85 if (Array
.isArray(msg
.result
)) {
86 ret
= (msg
.result
.length
> 1) ? msg
.result
[1] : msg
.result
[0];
90 for (var key
in req
.expect
) {
91 if (ret
!= null && key
!= '')
94 if (ret
== null || type
.call(ret
) != type
.call(req
.expect
[key
]))
95 ret
= req
.expect
[key
];
102 if (typeof(req
.filter
) == 'function') {
104 req
.priv
[1] = req
.params
;
105 ret
= req
.filter
.apply(this, req
.priv
);
116 params
: arguments
.length
? this.varargs(arguments
) : undefined
119 return this.call(msg
, this.handleListReply
);
122 declare: function(options
) {
123 return Function
.prototype.bind
.call(function(rpc
, options
) {
124 var args
= this.varargs(arguments
, 2);
125 return new Promise(function(resolveFn
, rejectFn
) {
126 /* build parameter object */
129 if (Array
.isArray(options
.params
))
130 for (p_off
= 0; p_off
< options
.params
.length
; p_off
++)
131 params
[options
.params
[p_off
]] = args
[p_off
];
133 /* all remaining arguments are private args */
134 var priv
= [ undefined, undefined ];
135 for (; p_off
< args
.length
; p_off
++)
136 priv
.push(args
[p_off
]);
138 /* store request info */
140 expect
: options
.expect
,
141 filter
: options
.filter
,
146 object
: options
.object
,
147 method
: options
.method
150 /* build message object */
164 rpc
.call(msg
, rpc
.parseCallReply
.bind(rpc
, req
));
166 }, this, this, options
);
169 getSessionID: function() {
173 setSessionID: function(sid
) {
177 getBaseURL: function() {
181 setBaseURL: function(url
) {
185 getStatusText: function(statusCode
) {
186 switch (statusCode
) {
187 case 0: return _('Command OK');
188 case 1: return _('Invalid command');
189 case 2: return _('Invalid argument');
190 case 3: return _('Method not found');
191 case 4: return _('Resource not found');
192 case 5: return _('No data received');
193 case 6: return _('Permission denied');
194 case 7: return _('Request timeout');
195 case 8: return _('Not supported');
196 case 9: return _('Unspecified error');
197 case 10: return _('Connection lost');
198 default: return _('Unknown error code');
202 addInterceptor: function(interceptorFn
) {
203 if (typeof(interceptorFn
) == 'function')
204 rpcInterceptorFns
.push(interceptorFn
);
205 return interceptorFn
;
208 removeInterceptor: function(interceptorFn
) {
209 var oldlen
= rpcInterceptorFns
.length
, i
= oldlen
;
211 if (rpcInterceptorFns
[i
] === interceptorFn
)
212 rpcInterceptorFns
.splice(i
, 1);
213 return (rpcInterceptorFns
.length
< oldlen
);