Fix manager reconnection bug in server. Add ClientTracker persistence.
Esse commit está contido em:
pai
5f0e7dd5fd
commit
05894bb136
|
@ -5,3 +5,4 @@ servers.conf
|
|||
recordings/*
|
||||
sounds/*
|
||||
*.sqlite3
|
||||
*.shelve
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
|
||||
# See LICENSE.txt for copyright info
|
||||
|
||||
import shelve
|
||||
from twisted.python import log
|
||||
|
||||
|
||||
class ClientTracker(object):
|
||||
|
||||
def __init__(self, cbClient, cbNet, cbMute, cbBlock, cbAdmin):
|
||||
def __init__(self, filename, cbClient, cbNet, cbMute, cbBlock, cbAdmin):
|
||||
self._clientData = {}
|
||||
self._net = {}
|
||||
self._mute = {}
|
||||
|
@ -19,6 +20,24 @@ class ClientTracker(object):
|
|||
self.cbMute = cbMute
|
||||
self.cbBlock = cbBlock
|
||||
self.cbAdmin = cbAdmin
|
||||
self.filename = filename
|
||||
self.load()
|
||||
|
||||
def load(self, filename=None):
|
||||
s = shelve.open(filename or self.filename)
|
||||
try:
|
||||
self._mute = s['mute']
|
||||
self._block = s['block']
|
||||
self._admin = s['admin']
|
||||
except KeyError: pass
|
||||
s.close()
|
||||
|
||||
def save(self, filename=None):
|
||||
s = shelve.open(filename or self.filename)
|
||||
s['mute'] = self._mute
|
||||
s['block'] = self._block
|
||||
s['admin'] = self._admin
|
||||
s.close()
|
||||
|
||||
def getClient(self, clientId):
|
||||
return self._clientData[clientId].user
|
||||
|
@ -76,7 +95,7 @@ class ClientTracker(object):
|
|||
if clientId in self._mute:
|
||||
client.user.M = 1
|
||||
a = self._mute[clientId].AI
|
||||
self._mute[clientId].update(client.user.dict())
|
||||
self._mute[clientId].update(**client.user.dict())
|
||||
self._mute[clientId].AI = a
|
||||
else:
|
||||
client.user.M = 0
|
||||
|
@ -85,6 +104,7 @@ class ClientTracker(object):
|
|||
if client.user.EA in self._admin:
|
||||
client.role = "ADMIN"
|
||||
self._admin[client.user.EA].update(client.user.dict())
|
||||
self.save()
|
||||
if len(nc) == 1:
|
||||
self.cbNet(self.getNetworkList())
|
||||
self.cbClient(net, self.getClientList(net))
|
||||
|
@ -101,6 +121,7 @@ class ClientTracker(object):
|
|||
if not self._net[net]:
|
||||
del self._net[net]
|
||||
self.cbNet(self.getNetworkList())
|
||||
self.save()
|
||||
self.cbClient(net, self.getClientList(net))
|
||||
|
||||
def setStatus(self, clientId, status):
|
||||
|
@ -114,6 +135,7 @@ class ClientTracker(object):
|
|||
if clientId not in self._mute:
|
||||
self._mute[clientId] = self.getClient(clientId).copy(AI=admin.ON)
|
||||
self._clientData[clientId].user.M = 1
|
||||
self.save()
|
||||
net = self.getClient(clientId).NT
|
||||
self.cbClient(net, self.getClientList(net))
|
||||
self.cbMute(self.getMuteList())
|
||||
|
@ -125,6 +147,7 @@ class ClientTracker(object):
|
|||
self._clientData[clientId].user.M = 0
|
||||
net = self._clientData[clientId].user.NT
|
||||
self.cbClient(net, self.getClientList(net))
|
||||
self.save()
|
||||
self.cbMute(self.getMuteList())
|
||||
|
||||
def block(self, admin, clientId):
|
||||
|
@ -132,21 +155,25 @@ class ClientTracker(object):
|
|||
self._block[clientId] = self.getClient(clientId).copy(AI=admin.ON)
|
||||
if clientId in self._clientData:
|
||||
net = self._clientData[clientId].user.NT
|
||||
self.save()
|
||||
self.cbBlock(self.getBlockList())
|
||||
|
||||
def unBlock(self, clientId):
|
||||
if clientId in self._block:
|
||||
del self._block[clientId]
|
||||
self.save()
|
||||
self.cbBlock(self.getBlockList())
|
||||
|
||||
def admin(self, clientId):
|
||||
if clientId not in self._admin:
|
||||
self._admin[clientId] = self.getClient(clientId).copy()
|
||||
self.save()
|
||||
self.cbAdmin(self.getAdminList())
|
||||
|
||||
def unAdmin(self, clientId):
|
||||
if clientId in self._admin:
|
||||
del self._admin[clientId]
|
||||
self.save()
|
||||
self.cbAdmin(self.getAdminList())
|
||||
|
||||
|
||||
|
|
|
@ -12,45 +12,28 @@ from frn.protocol.manager import FRNManagerClient, FRNManagerClientFactory
|
|||
|
||||
class CustomManagerClientFactory(FRNManagerClientFactory):
|
||||
|
||||
def __init__(self, user, onConnect, onDisconnect):
|
||||
def __init__(self, user):
|
||||
self.user = user
|
||||
self.onConnect = onConnect
|
||||
self.onDisconnect = onDisconnect
|
||||
self.authResult = False
|
||||
self.client = None
|
||||
self.managerReady = Deferred()
|
||||
self.client = None
|
||||
self.authDone = False
|
||||
self.deferred = Deferred()
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
self.authResult = False
|
||||
self.client = None
|
||||
self.managerReady = Deferred()
|
||||
self.onDisconnect(self.protocol)
|
||||
FRNManagerClientFactory.clientConnectionFailed(
|
||||
self, connector, reason)
|
||||
self.managerConnection.addCallback(self.connectionReady)
|
||||
def managerConnected(self, connection):
|
||||
def authReply(auth):
|
||||
self.authResult = auth
|
||||
self.authDone = (auth['al'] == '0')
|
||||
if self.authDone:
|
||||
self.deferred.callback(auth)
|
||||
connection.sendServerLogin(self.user).addCallback(authReply)
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
self.authResult = False
|
||||
self.client = None
|
||||
self.managerReady = Deferred()
|
||||
self.onDisconnect(self.protocol)
|
||||
FRNManagerClientFactory.clientConnectionLost(
|
||||
self, connector, reason)
|
||||
self.managerConnection.addCallback(self.connectionReady)
|
||||
def managerDisconnected(self, connection):
|
||||
pass
|
||||
|
||||
def connectionReady(self, client):
|
||||
def authDone(res):
|
||||
log.msg("Auth: %s" % str(res))
|
||||
if res['al'] == '0':
|
||||
self.authResult = res
|
||||
self.onConnect(client)
|
||||
self.managerReady.callback(res)
|
||||
else:
|
||||
client.transport.loseConnection()
|
||||
return res
|
||||
self.client = client
|
||||
self.client.sendServerLogin(self.user).addCallback(authDone)
|
||||
def buildProtocol(self, addr):
|
||||
p = FRNManagerClientFactory.buildProtocol(self, addr)
|
||||
self.client = p
|
||||
return p
|
||||
|
||||
|
||||
class RemoteManager(object):
|
||||
|
@ -63,21 +46,13 @@ class RemoteManager(object):
|
|||
self.port = port
|
||||
self.factory = None
|
||||
|
||||
def onManagerConnect(self, protocol):
|
||||
pass
|
||||
|
||||
def onManagerDisconnect(self, protocol):
|
||||
pass
|
||||
|
||||
def doConnect(self):
|
||||
self.reactor.connectTCP(self.server, self.port, self.factory)
|
||||
self.factory.managerConnection.addCallback(self.factory.connectionReady)
|
||||
return self.factory.managerReady
|
||||
|
||||
def serverLogin(self, user):
|
||||
self.factory = CustomManagerClientFactory(
|
||||
user, self.onManagerConnect, self.onManagerDisconnect)
|
||||
return self.doConnect()
|
||||
self.factory = CustomManagerClientFactory(user)
|
||||
self.doConnect()
|
||||
return self.factory.deferred
|
||||
|
||||
def serverLogout(self, user):
|
||||
if self.factory.client is not None:
|
||||
|
|
|
@ -20,9 +20,7 @@ class FRNManagerClient(LineOnlyReceiver):
|
|||
def connectionMade(self):
|
||||
log.msg("Connected to manager [%s]" % self.transport.getPeer().host)
|
||||
self.notifications = []
|
||||
if not self.factory.managerConnection.called: # FIXME: Why???
|
||||
log.msg("Firing manager connection callback!")
|
||||
self.factory.managerConnection.callback(self)
|
||||
self.factory.managerConnected(self)
|
||||
|
||||
def connectionLost(self, reason):
|
||||
log.msg("Manager disconnected")
|
||||
|
@ -31,7 +29,7 @@ class FRNManagerClient(LineOnlyReceiver):
|
|||
except: pass
|
||||
for d in self.notifications:
|
||||
d.errback(reason)
|
||||
self.factory.managerConnection = Deferred()
|
||||
self.factory.managerDisconnected(self)
|
||||
|
||||
def notifyFinish(self):
|
||||
self.notifications.append(Deferred())
|
||||
|
@ -102,8 +100,11 @@ class FRNManagerClientFactory(ReconnectingClientFactory):
|
|||
|
||||
protocol = FRNManagerClient
|
||||
|
||||
def startFactory(self):
|
||||
self.managerConnection = Deferred()
|
||||
def managerConnected(self, connection):
|
||||
pass
|
||||
|
||||
def managerDisconnected(self, connection):
|
||||
pass
|
||||
|
||||
|
||||
class FRNManagerServer(LineOnlyReceiver):
|
||||
|
|
|
@ -110,9 +110,9 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
|
|||
def authReturned(result):
|
||||
self.role, clientId = result
|
||||
log.msg("AUTH result: %s %s" % (self.role, clientId))
|
||||
self.user = FRNUser(**body)
|
||||
self.user.ID = clientId
|
||||
if self.role == 'OK':
|
||||
self.user = FRNUser(**body)
|
||||
self.user.ID = clientId
|
||||
if self.user.EA == self.factory.serverAuth.OW:
|
||||
self.role = 'OWNER'
|
||||
elif self.factory.tracker.isAdmin(self.user.EA):
|
||||
|
@ -272,12 +272,13 @@ class FRNServerFactory(ServerFactory):
|
|||
|
||||
protocol = FRNServer
|
||||
|
||||
def __init__(self, manager, serverAuth):
|
||||
def __init__(self, trackerfile, manager, serverAuth):
|
||||
self.manager = manager
|
||||
self.serverAuth = serverAuth
|
||||
self.talking = None
|
||||
self.officialNets = []
|
||||
self.tracker = ClientTracker(
|
||||
trackerfile,
|
||||
self.sendClientList, self.sendNetworkList,
|
||||
self.sendMuteList, self.sendBlockList,
|
||||
self.sendAdminList)
|
||||
|
|
|
@ -43,6 +43,7 @@ if __name__ == '__main__':
|
|||
password = acfg.get(account_name, 'password')
|
||||
|
||||
reactor.listenTCP(10024, FRNServerFactory(
|
||||
pjoin(basedir, 'tracker.shelve'),
|
||||
# DatabaseUserStore(
|
||||
# ConnectionPool("sqlite3", "frn_users.sqlite3",
|
||||
# check_same_thread=False)),
|
||||
|
|
Carregando…
Referência em uma nova issue