webui-aria2/js/services/rpc/rpc.js

233 lines
6.8 KiB
JavaScript
Raw Normal View History

angular
2013-03-02 12:01:07 +01:00
.module('webui.services.rpc', [
'webui.services.rpc.syscall', 'webui.services.constants', 'webui.services.alerts',
'webui.services.utils'
2013-03-02 12:01:07 +01:00
])
2013-03-12 07:51:44 +01:00
.factory('$rpc', [
'$syscall', '$globalTimeout', '$alerts', '$utils',
'$rootScope', '$location',
function(syscall, time, alerts, utils, rootScope, uri) {
2013-03-02 12:01:07 +01:00
var subscriptions = []
, configurations = [{ host: 'localhost', port: 6800, encrypt: false }]
2013-03-02 12:01:07 +01:00
, currentConf = {}
2014-05-17 17:41:00 +02:00
, currentToken
, timeout = null
, forceNextUpdate = false;
if (['http', 'https'].indexOf(uri.protocol()) != -1 && uri.host() != 'localhost') {
console.log(uri.host());
configurations.unshift({
host: uri.host(),
port: 6800,
encrypt: false
});
console.log(configurations);
}
var cookieConf = utils.getCookie('aria2conf');
// try at the end, so that it is not overwridden in case it doesnt work
2014-05-31 14:42:09 +02:00
if (cookieConf) configurations.unshift(cookieConf);
// update is implemented such that
// only one syscall at max is ongoing
// (i.e. serially) so should be private
// to maintain that invariant
var update = function() {
2013-03-02 12:01:07 +01:00
clearTimeout(timeout);
timeout = null;
2014-01-09 04:18:44 +01:00
subscriptions = _.filter(subscriptions, function(e) {
2014-03-14 13:59:12 +01:00
return !!e && e.once !== 2;
2014-01-09 04:18:44 +01:00
});
var subs = subscriptions.slice();
if (!subs.length) {
2013-03-02 12:01:07 +01:00
timeout = setTimeout(update, time);
return;
2013-03-02 12:01:07 +01:00
}
2013-03-02 12:01:07 +01:00
if (configurations.length) {
2014-05-31 14:42:09 +02:00
currentConf = configurations[0];
2014-05-17 17:41:00 +02:00
if (currentConf && currentConf.auth && currentConf.auth.token) {
currentToken = currentConf.auth.token;
}
else {
currentToken = null;
}
2013-03-02 12:01:07 +01:00
syscall.init(currentConf);
}
2014-01-09 04:18:44 +01:00
var params = _.map(subs, function(s) {
2014-05-17 17:41:00 +02:00
var p = s.params;
if (currentToken) {
p = ["token:" + currentToken].concat(p || []);
}
return {
methodName: s.name,
2014-05-17 17:41:00 +02:00
params: p && p.length ? p : undefined
};
});
2014-05-17 17:41:00 +02:00
var error = function() {
2014-05-31 14:42:09 +02:00
var ind = configurations.indexOf(currentConf);
if (ind != -1) configurations.splice(ind, 1);
2014-05-17 17:41:00 +02:00
// If some proposed configurations are still in the pipeline then retry
if (configurations.length) {
alerts.log("The last connection attempt was unsuccessful. Trying another configuration");
timeout = setTimeout(update, 0);
}
else {
2014-05-31 14:42:09 +02:00
alerts.addAlert('<strong>Oh Snap!</strong> Could not connect to the aria2 RPC server. Will retry in 10 secs. You might want to check the connection settings by going to Settings > Connection Settings', 'error');
timeout = setTimeout(update, 10000);
2014-05-17 17:41:00 +02:00
}
};
syscall.invoke({
name: 'system.multicall',
params: [params],
success: function(data) {
2014-05-17 17:41:00 +02:00
var failed = _.any(data.result, function(d) {
return d.code && d.message === "Unauthorized";
});
2014-05-31 14:42:09 +02:00
2014-05-17 17:41:00 +02:00
if (failed) {
2014-05-31 14:42:09 +02:00
alerts.addAlert('<strong>Oh Snap!</strong> Authentication failed while connecting to Aria2 RPC server. Will retry in 10 secs. You might want to confirm your authentication details by going to Settings > Connection Settings', 'error');
timeout = setTimeout(update, 10000);
2014-05-17 17:41:00 +02:00
return;
}
2013-03-02 12:01:07 +01:00
if (configurations.length) {
// configuration worked, save it in cookie for next time and
// delete the pipelined configurations!!
if (currentToken)
alerts.addAlert('Successfully connected to Aria2 through its remote RPC …', 'success');
else
alerts.addAlert('Successfully connected to Aria2 through remote RPC, however the connection is still insecure. For complete security try adding an authorization secret token while starting Aria2 (through the flag --rpc-secret)');
2013-03-02 12:01:07 +01:00
configurations = [];
}
utils.setCookie('aria2conf', currentConf);
var cbs = [];
_.each(data.result, function(d, i) {
2014-01-09 04:18:44 +01:00
var handle = subs[i];
if (handle) {
if (d.code) {
2014-01-09 04:18:44 +01:00
console.error(handle, d);
alerts.addAlert(d.message, 'error');
}
// run them later as the cb itself can mutate the subscriptions
cbs.push({cb: handle.cb, data: d});
if (handle.once) {
2014-01-09 04:18:44 +01:00
handle.once = 2;
}
}
});
_.each(cbs, function(hnd) {
hnd.cb(hnd.data);
});
rootScope.$digest();
2013-03-12 07:51:44 +01:00
if (forceNextUpdate) {
forceNextUpdate = false;
2013-03-02 12:01:07 +01:00
timeout = setTimeout(update, 0);
}
else {
timeout = setTimeout(update, time);
}
},
2014-05-17 17:41:00 +02:00
error: error
});
2013-03-02 12:01:07 +01:00
};
// initiate the update loop
timeout = setTimeout(update, time);
return {
// conf can be configuration or array of configurations,
// each one will be tried one after the other till success,
// for all options for one conf read rpc/syscall.js
configure: function(conf) {
2014-05-31 14:42:09 +02:00
alerts.addAlert('Trying to connect to aria2 using the new connection configuration', 'info');
if (conf instanceof Array)
configurations = conf;
else
configurations = [conf];
2014-05-31 14:42:09 +02:00
if (timeout) {
clearTimeout(timeout);
timeout = setTimeout(update, 0);
}
},
// get current configuration being used
getConfiguration: function() { return currentConf },
// syscall is done only once, delay is optional
// and pass true to only dispatch it in the global timeout
// which can be used to batch up once calls
once: function(name, params, cb, delay) {
cb = cb || angular.noop;
params = params || [];
subscriptions.unshift({
once: true,
name: 'aria2.' + name,
params: params,
cb: cb
});
if (!delay) {
this.forceUpdate();
}
},
// callback is called each time with updated syscall data
// after the global timeout, delay is optional and pass it
// true to dispatch the first syscall also on global timeout
// which can be used to batch the subscribe calls
subscribe: function(name, params, cb, delay) {
cb = cb || angular.noop;
params = params || [];
var handle = {
once: false,
name: 'aria2.' + name,
params: params,
cb: cb
};
subscriptions.push(handle);
if (!delay) this.forceUpdate();
return handle;
},
// remove the subscribed callback by passing
// the returned handle bysubscribe
unsubscribe: function(handle) {
var ind = subscriptions.indexOf(handle);
subscriptions[ind] = null;
},
// force the global syscall update
forceUpdate: function() {
if (timeout) {
clearTimeout(timeout);
2013-03-02 12:01:07 +01:00
timeout = setTimeout(update, 0);
}
else {
// a batch call is already in progress,
// wait till it returns and force the next one
forceNextUpdate = true;
}
}
};
}]);