Move deluge errors to the errors module, they will be reused later on other parts of code.
Now, calling connect on client has two behaviours, if username/password is passed the client connects, authenticates and returns daemon info, if username/password is not passed, only the daemon info is returned. This might change a bit later on though.
This commit is contained in:
parent
e17c035521
commit
b2a16a0240
|
@ -198,6 +198,8 @@ class Daemon(object):
|
|||
|
||||
:returns: str, the version number
|
||||
"""
|
||||
print '\n\ndaemon.info called\n\n'
|
||||
|
||||
return deluge.common.get_version()
|
||||
|
||||
@export()
|
||||
|
|
|
@ -55,7 +55,8 @@ except ImportError:
|
|||
|
||||
import deluge.component as component
|
||||
import deluge.configmanager
|
||||
from deluge.core.authmanager import AUTH_LEVEL_NONE, AUTH_LEVEL_DEFAULT
|
||||
from deluge.core.authmanager import AUTH_LEVEL_NONE, AUTH_LEVEL_DEFAULT, AUTH_LEVEL_ADMIN
|
||||
from deluge.error import DelugeError, NotAuthorizedError
|
||||
|
||||
RPC_RESPONSE = 1
|
||||
RPC_ERROR = 2
|
||||
|
@ -117,12 +118,6 @@ def format_request(call):
|
|||
else:
|
||||
return s
|
||||
|
||||
class DelugeError(Exception):
|
||||
pass
|
||||
|
||||
class NotAuthorizedError(DelugeError):
|
||||
pass
|
||||
|
||||
class ServerContextFactory(object):
|
||||
def getContext(self):
|
||||
"""
|
||||
|
@ -253,24 +248,10 @@ class DelugeRPCProtocol(Protocol):
|
|||
"".join(traceback.format_tb(exceptionTraceback)))
|
||||
))
|
||||
|
||||
if method == "daemon.peek":
|
||||
if method == "daemon.info":
|
||||
# This is a special case and used in the initial connection process
|
||||
# We need to peek the user here in order to get an auth level back
|
||||
# and see if the user exists.
|
||||
try:
|
||||
ret = component.get("AuthManager").peek(*args, **kwargs)
|
||||
if ret:
|
||||
self.factory.authorized_sessions[self.transport.sessionno] = (ret, args[0])
|
||||
self.factory.session_protocols[self.transport.sessionno] = self
|
||||
except Exception, e:
|
||||
sendError()
|
||||
log.exception(e)
|
||||
else:
|
||||
self.sendData((RPC_RESPONSE, request_id, ret))
|
||||
if not ret:
|
||||
self.transport.loseConnection()
|
||||
finally:
|
||||
return
|
||||
self.sendData((RPC_RESPONSE, request_id, deluge.common.get_version()))
|
||||
return
|
||||
elif method == "daemon.login":
|
||||
# This is a special case and used in the initial connection process
|
||||
# We need to authenticate the user here
|
||||
|
@ -374,6 +355,7 @@ class RPCServer(component.Component):
|
|||
# Holds the interested event list for the sessions
|
||||
self.factory.interested_events = {}
|
||||
|
||||
self.listen = listen
|
||||
if not listen:
|
||||
return
|
||||
|
||||
|
@ -458,6 +440,8 @@ class RPCServer(component.Component):
|
|||
:rtype: string
|
||||
|
||||
"""
|
||||
if not self.listen:
|
||||
return "localclient"
|
||||
session_id = self.get_session_id()
|
||||
if session_id > -1 and session_id in self.factory.authorized_sessions:
|
||||
return self.factory.authorized_sessions[session_id][1]
|
||||
|
@ -472,6 +456,8 @@ class RPCServer(component.Component):
|
|||
:returns: the auth level
|
||||
:rtype: int
|
||||
"""
|
||||
if not self.listen:
|
||||
return AUTH_LEVEL_ADMIN
|
||||
return self.factory.authorized_sessions[self.get_session_id()][0]
|
||||
|
||||
def get_rpc_auth_level(self, rpc):
|
||||
|
|
|
@ -48,3 +48,14 @@ class InvalidTorrentError(DelugeError):
|
|||
|
||||
class InvalidPathError(DelugeError):
|
||||
pass
|
||||
|
||||
class NotAuthorizedError(DelugeError):
|
||||
pass
|
||||
|
||||
class BadLoginError(DelugeError):
|
||||
pass
|
||||
|
||||
class AuthenticationRequired(BadLoginError):
|
||||
def __init__(self, message, username):
|
||||
super(AuthenticationRequired, self).__init__(message)
|
||||
self.username = username
|
||||
|
|
|
@ -261,27 +261,7 @@ class DaemonSSLProxy(DaemonProxy):
|
|||
self.disconnect_deferred = None
|
||||
self.disconnect_callback = None
|
||||
|
||||
def peek(self, host, port, username):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.__connector = reactor.connectSSL(self.host, self.port, self.__factory, ssl.ClientContextFactory())
|
||||
self.connect_deferred = defer.Deferred()
|
||||
self.peek_deferred = defer.Deferred()
|
||||
|
||||
def on_connect(result, username):
|
||||
self.__login_deferred = self.call("daemon.peek", username)
|
||||
self.__login_deferred.addCallback(self.__on_peek, username)
|
||||
self.__login_deferred.addErrback(self.__on_peek_fail)
|
||||
|
||||
def on_connect_fail(reason):
|
||||
log.debug("connect_fail: %s", reason)
|
||||
self.peek_deferred.errback(reason)
|
||||
|
||||
self.connect_deferred.addCallback(on_connect, username)
|
||||
self.connect_deferred.addErrback(on_connect_fail)
|
||||
return self.peek_deferred
|
||||
|
||||
def connect(self, host, port, username, password):
|
||||
def connect(self, host, port):
|
||||
"""
|
||||
Connects to a daemon at host:port
|
||||
|
||||
|
@ -298,13 +278,13 @@ class DaemonSSLProxy(DaemonProxy):
|
|||
self.port = port
|
||||
self.__connector = reactor.connectSSL(self.host, self.port, self.__factory, ssl.ClientContextFactory())
|
||||
self.connect_deferred = defer.Deferred()
|
||||
self.login_deferred = defer.Deferred()
|
||||
self.daemon_info_deferred = defer.Deferred()
|
||||
|
||||
# Upon connect we do a 'daemon.login' RPC
|
||||
self.connect_deferred.addCallback(self.__on_connect, username, password)
|
||||
self.connect_deferred.addCallback(self.__on_connect)
|
||||
self.connect_deferred.addErrback(self.__on_connect_fail)
|
||||
|
||||
return self.login_deferred
|
||||
return self.daemon_info_deferred
|
||||
|
||||
def disconnect(self):
|
||||
log.debug("sslproxy.disconnect()")
|
||||
|
@ -418,19 +398,37 @@ class DaemonSSLProxy(DaemonProxy):
|
|||
log.error(msg)
|
||||
return error_data
|
||||
|
||||
def __on_connect(self, result, username, password):
|
||||
def __on_connect(self, result):
|
||||
log.debug("__on_connect called")
|
||||
self.__login_deferred = self.call("daemon.login", username, password)
|
||||
self.__login_deferred.addCallback(self.__on_login, username)
|
||||
self.__login_deferred.addErrback(self.__on_login_fail)
|
||||
|
||||
def on_info(daemon_info):
|
||||
self.daemon_info = daemon_info
|
||||
log.debug("Got info from daemon: %s", daemon_info)
|
||||
self.daemon_info_deferred.callback(daemon_info)
|
||||
|
||||
def on_info_fail(reason):
|
||||
log.debug("Failed to get info from daemon: %s", reason)
|
||||
self.daemon_info_deferred.errback(reason)
|
||||
|
||||
self.call("daemon.info").addCallback(on_info).addErrback(on_info_fail)
|
||||
return self.daemon_info_deferred
|
||||
|
||||
def __on_connect_fail(self, reason):
|
||||
log.debug("__on_connect_fail called")
|
||||
log.debug("connect_fail: %s", reason)
|
||||
self.login_deferred.errback(reason)
|
||||
log.exception(reason)
|
||||
self.daemon_info_deferred.errback(reason)
|
||||
|
||||
def authenticate(self, username, password):
|
||||
log.debug("%s.authenticate: %s", self.__class__.__name__, username)
|
||||
self.login_deferred = defer.Deferred()
|
||||
d = self.call("daemon.login", username, password)
|
||||
d.addCallback(self.__on_login, username)
|
||||
d.addErrback(self.__on_login_fail)
|
||||
return self.login_deferred
|
||||
|
||||
def __on_login(self, result, username):
|
||||
log.debug("__on_login called")
|
||||
log.debug("__on_login called: %s %s", username, result)
|
||||
self.username = username
|
||||
# We need to tell the daemon what events we're interested in receiving
|
||||
if self.__factory.event_handlers:
|
||||
|
@ -441,15 +439,6 @@ class DaemonSSLProxy(DaemonProxy):
|
|||
log.debug("_on_login_fail(): %s", result)
|
||||
self.login_deferred.errback(result)
|
||||
|
||||
def __on_peek(self, result, username):
|
||||
log.debug("__on_peek called. result: %s", result)
|
||||
self.username = username
|
||||
self.peek_deferred.callback(result)
|
||||
|
||||
def __on_peek_fail(self, result):
|
||||
log.debug("__on_peek_fail called. result: %s", result)
|
||||
self.peek_deferred.errback(result)
|
||||
|
||||
def set_disconnect_callback(self, cb):
|
||||
"""
|
||||
Set a function to be called when the connection to the daemon is lost
|
||||
|
@ -471,7 +460,10 @@ class DaemonClassicProxy(DaemonProxy):
|
|||
self.connected = True
|
||||
self.host = "localhost"
|
||||
self.port = 58846
|
||||
# Running in classic mode, it's safe to import auth level
|
||||
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
||||
self.username = "localclient"
|
||||
self.authentication_level = AUTH_LEVEL_ADMIN
|
||||
# Register the event handlers
|
||||
for event in event_handlers:
|
||||
for handler in event_handlers[event]:
|
||||
|
@ -574,32 +566,55 @@ class Client(object):
|
|||
|
||||
self._daemon_proxy = DaemonSSLProxy(dict(self.__event_handlers))
|
||||
self._daemon_proxy.set_disconnect_callback(self.__on_disconnect)
|
||||
d = self._daemon_proxy.connect(host, port, username, password)
|
||||
d = self._daemon_proxy.connect(host, port)
|
||||
def on_connect_fail(result):
|
||||
log.debug("on_connect_fail: %s", result)
|
||||
self.disconnect()
|
||||
return result
|
||||
|
||||
d.addErrback(on_connect_fail)
|
||||
|
||||
if username or password:
|
||||
auth_deferred = defer.Deferred()
|
||||
|
||||
def on_authenticate(result, daemon_info):
|
||||
log.debug("Authentication sucessfull: %s", result)
|
||||
self.authentication_level = result
|
||||
auth_deferred.callback(daemon_info)
|
||||
|
||||
def on_authenticate_fail(reason):
|
||||
log.debug("Failed to authenticate")
|
||||
log.exception(reason)
|
||||
auth_deferred.errback(reason)
|
||||
|
||||
def on_connected(daemon_version):
|
||||
log.debug("Client.connect.on_connected: %s", daemon_version)
|
||||
print 1234, self._daemon_proxy
|
||||
d = self._daemon_proxy.authenticate(username, password)
|
||||
print 1234, d
|
||||
d.addCallback(on_authenticate, daemon_version)
|
||||
d.addErrback(on_authenticate_fail)
|
||||
# return d
|
||||
|
||||
d.addCallback(on_connected)
|
||||
return auth_deferred
|
||||
return d
|
||||
|
||||
def peek(self, host="127.0.0.1", port=58846, username=""):
|
||||
if not username and host in ("127.0.0.1", "localhost"):
|
||||
# No username was provided and it's the localhost, so we can try
|
||||
# to grab the credentials from the auth file.
|
||||
import common
|
||||
username, password = common.get_localhost_auth()
|
||||
|
||||
self._daemon_proxy = DaemonSSLProxy(dict(self.__event_handlers))
|
||||
self._daemon_proxy.set_disconnect_callback(self.__on_disconnect)
|
||||
d = self._daemon_proxy.peek(host, port, username)
|
||||
def on_connect_fail(result):
|
||||
log.debug("on_connect_fail: %s", result)
|
||||
self.disconnect()
|
||||
return result
|
||||
|
||||
d.addErrback(on_connect_fail)
|
||||
return d
|
||||
# def authenticate(self, username="", password=""):
|
||||
# if not self.connected():
|
||||
# raise Exception("You first need to call connect")
|
||||
# if not username and self._daemon_proxy.host in ("127.0.0.1", "localhost"):
|
||||
# # No username was provided and it's the localhost, so we can try
|
||||
# # to grab the credentials from the auth file.
|
||||
# import common
|
||||
# username, password = common.get_localhost_auth()
|
||||
#
|
||||
# def on_authenticate_fail(reason):
|
||||
# log.debug("Failed to authenticate %s@%s:%s")
|
||||
#
|
||||
# d = self._daemon_proxy.authenticate(username, password)
|
||||
# d.addErrback(on_authenticate_fail)
|
||||
# return d
|
||||
|
||||
def disconnect(self):
|
||||
"""
|
||||
|
@ -646,6 +661,10 @@ class Client(object):
|
|||
else:
|
||||
return True
|
||||
|
||||
def daemon_info(self):
|
||||
return self._daemon_proxy.daemon_info_deferred
|
||||
return defer.succeed(self._daemon_proxy.daemon_info or None)
|
||||
|
||||
def is_localhost(self):
|
||||
"""
|
||||
Checks if the current connected host is a localhost or not.
|
||||
|
|
|
@ -300,6 +300,7 @@ class ConnectionManager(component.Component):
|
|||
row = self.__get_host_row(host_id)
|
||||
if row:
|
||||
row[HOSTLIST_COL_STATUS] = _("Offline")
|
||||
# row[HOSTLIST_COL_VERSION] = ""
|
||||
self.__update_buttons()
|
||||
|
||||
for row in self.liststore:
|
||||
|
@ -307,22 +308,30 @@ class ConnectionManager(component.Component):
|
|||
host = row[HOSTLIST_COL_HOST]
|
||||
port = row[HOSTLIST_COL_PORT]
|
||||
user = row[HOSTLIST_COL_USER]
|
||||
password = row[HOSTLIST_COL_PASS]
|
||||
|
||||
if client.connected() and \
|
||||
(host, port, "localclient" if not user and host in ("127.0.0.1", "localhost") else user) == client.connection_info():
|
||||
def on_info(info):
|
||||
log.debug("\n\nClient connected, query info: %s:%s\n\n", info, self.running)
|
||||
if not self.running:
|
||||
return
|
||||
row[HOSTLIST_COL_VERSION] = info
|
||||
self.__update_buttons()
|
||||
print row[HOSTLIST_COL_ID], row[HOSTLIST_COL_HOST], row[HOSTLIST_COL_PORT], row[HOSTLIST_COL_USER], row[HOSTLIST_COL_VERSION]
|
||||
|
||||
def on_info_fail(reason):
|
||||
print '\n\n'
|
||||
log.exception(reason)
|
||||
print '\n\n'
|
||||
|
||||
row[HOSTLIST_COL_STATUS] = _("Connected")
|
||||
client.daemon.info().addCallback(on_info)
|
||||
log.debug("\n\nquery daemons info\n\n")
|
||||
client.daemon.info().addCallback(on_info).addErrback(on_info_fail)
|
||||
continue
|
||||
|
||||
# Create a new Client instance
|
||||
c = deluge.ui.client.Client()
|
||||
d = c.peek(host, port, user)
|
||||
d = c.connect(host, port)
|
||||
d.addCallback(on_connect, c, host_id)
|
||||
d.addErrback(on_connect_failed, host_id)
|
||||
|
||||
|
@ -435,11 +444,11 @@ that you forgot to install the deluged package or it's not in your PATH.")).run(
|
|||
details=traceback.format_exc(tb[2])).run()
|
||||
|
||||
# Signal handlers
|
||||
def __connect(self, host_id, host, port, user, password):
|
||||
def __connect(self, host_id, host, port, username, password):
|
||||
def do_connect(*args):
|
||||
d = client.connect(host, port, user, password)
|
||||
d = client.connect(host, port, username, password)
|
||||
d.addCallback(self.__on_connected, host_id)
|
||||
d.addErrback(self.__on_connected_failed, host_id, host, port, user)
|
||||
d.addErrback(self.__on_connected_failed, host_id, host, port, username)
|
||||
return d
|
||||
|
||||
if client.connected():
|
||||
|
@ -447,16 +456,25 @@ that you forgot to install the deluged package or it's not in your PATH.")).run(
|
|||
else:
|
||||
return do_connect()
|
||||
|
||||
def __on_connected(self, connector, host_id):
|
||||
log.debug("__on_connected called")
|
||||
def __on_connected(self, daemon_info, host_id):
|
||||
# log.debug("__on_connected called for hostid: %s connector: %s",
|
||||
# host_id, daemon_info)
|
||||
if self.gtkui_config["autoconnect"]:
|
||||
self.gtkui_config["autoconnect_host_id"] = host_id
|
||||
|
||||
# row = self.__get_host_row(host_id)
|
||||
# row[HOSTLIST_COL_STATUS] = _("Connected")
|
||||
# row[HOSTLIST_COL_VERSION] = daemon_info
|
||||
#
|
||||
# # Update the status of the hosts
|
||||
# self.__update_list()
|
||||
|
||||
self.connection_manager.response(gtk.RESPONSE_OK)
|
||||
|
||||
component.start()
|
||||
|
||||
def __on_connected_failed(self, reason, host_id, host, port, user):
|
||||
log.exception(reason)
|
||||
if reason.value.exception_type == "PasswordRequired":
|
||||
log.debug("PasswordRequired exception")
|
||||
dialog = dialogs.AuthenticationDialog(reason.value.exception_msg)
|
||||
|
|
Loading…
Reference in New Issue