Browse Source

Fix manager reconnection bug in server. Add ClientTracker persistence.

wip
Maurizio Porrato 9 years ago
parent
commit
05894bb136
6 changed files with 63 additions and 57 deletions
  1. +1
    -0
      .gitignore
  2. +29
    -2
      frn/clienttracker.py
  3. +21
    -46
      frn/manager/remote.py
  4. +7
    -6
      frn/protocol/manager.py
  5. +4
    -3
      frn/protocol/server.py
  6. +1
    -0
      server.py

+ 1
- 0
.gitignore View File

@@ -5,3 +5,4 @@ servers.conf
recordings/*
sounds/*
*.sqlite3
*.shelve

+ 29
- 2
frn/clienttracker.py View File

@@ -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())



+ 21
- 46
frn/manager/remote.py View File

@@ -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 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 managerDisconnected(self, connection):
pass

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 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 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:

+ 7
- 6
frn/protocol/manager.py View File

@@ -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):

+ 4
- 3
frn/protocol/server.py View File

@@ -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)

+ 1
- 0
server.py View File

@@ -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)),

Loading…
Cancel
Save