Add new features

- Add first (buggy and dirty) server implementation
- Some bugfixes
This commit is contained in:
Maurizio Porrato 2010-08-21 17:32:22 +02:00
parent d4a1a0da99
commit 5f0e7dd5fd
13 changed files with 386 additions and 125 deletions

18
docs/accounts.conf.sample Normal file
View File

@ -0,0 +1,18 @@
[DEFAULT]
; Settings in DEFAULT section are inherited by all other sections
city=City - LOCATOR
country=Country
transmission=PC Only
description=
[testaccount]
operator=CALLSIGN, Operator name
email=testaccount@example.com
password=TOPSECRET
[myaccount]
operator=CALLSIGN, Operator name
email=otheremail@example.com
transmission=Parrot
password=SUPERSECRET

10
docs/servers.conf.sample Normal file
View File

@ -0,0 +1,10 @@
[DEFAULT]
port=10024
backup_server=
backup_port=10024
[FRI]
server=master.freeradionetwork.it
[NL]
server=ham.freeradionetwork.nl

View File

@ -1,9 +0,0 @@
[accountname]
operator=callsign, name
email=me@example.com
city=City - Locator
country=Your country
transmission=PC Only
description=
password=SECRET
network=Default network

153
frn/clienttracker.py Normal file
View File

@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
#
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
# See LICENSE.txt for copyright info
from twisted.python import log
class ClientTracker(object):
def __init__(self, cbClient, cbNet, cbMute, cbBlock, cbAdmin):
self._clientData = {}
self._net = {}
self._mute = {}
self._block = {}
self._admin = {}
self.cbClient = cbClient
self.cbNet = cbNet
self.cbMute = cbMute
self.cbBlock = cbBlock
self.cbAdmin = cbAdmin
def getClient(self, clientId):
return self._clientData[clientId].user
def getClientProtocol(self, clientId):
return self._clientData[clientId]
def getClientIndex(self, clientId):
net = self.getClient(clientId).NT
l = [x.ID for x in self.getClientList(net)]
return l.index(clientId)+1
def getNetworkList(self):
return self._net.keys()
def getClientList(self, network=[]):
if network:
allClients = self._net.get(network, [])
else:
allClients = self._clientData.keys()
return [self._clientData[x].user
for x in allClients]
def getMuteList(self, network=[]):
if network:
return [x for x in self._mute.values()
if self._mute[x.ID].NT in network]
else:
return [x for x in self._mute.values()]
def getBlockList(self):
return self._block.values()
def getAdminList(self):
return self._admin.values()
def isMute(self, clientId):
return clientId in self._mute
def isBlocked(self, clientId):
return clientId in self._block
def isAdmin(self, email):
return email in self._admin
def login(self, client, status=0):
clientId = client.user.ID
if clientId not in self._clientData:
client.user.S = status
self._clientData[clientId] = client
net = client.user.NT
nc = self._net.get(net, [])
nc.append(clientId)
self._net[net] = nc
if clientId in self._mute:
client.user.M = 1
a = self._mute[clientId].AI
self._mute[clientId].update(client.user.dict())
self._mute[clientId].AI = a
else:
client.user.M = 0
if clientId in self._block:
client.role = "BLOCK"
if client.user.EA in self._admin:
client.role = "ADMIN"
self._admin[client.user.EA].update(client.user.dict())
if len(nc) == 1:
self.cbNet(self.getNetworkList())
self.cbClient(net, self.getClientList(net))
def logout(self, client):
if client.user is None:
return
clientId = client.user.ID
log.msg("Client logout: %s" % (clientId,))
if clientId in self._clientData:
del self._clientData[clientId]
net = client.user.NT
self._net[net].remove(clientId)
if not self._net[net]:
del self._net[net]
self.cbNet(self.getNetworkList())
self.cbClient(net, self.getClientList(net))
def setStatus(self, clientId, status):
oldStatus = self._clientData[clientId].user.S
if oldStatus != str(status):
net = self._clientData[clientId].user.NT
self._clientData[clientId].user.S = status
self.cbClient(net, self.getClientList(net))
def mute(self, admin, clientId):
if clientId not in self._mute:
self._mute[clientId] = self.getClient(clientId).copy(AI=admin.ON)
self._clientData[clientId].user.M = 1
net = self.getClient(clientId).NT
self.cbClient(net, self.getClientList(net))
self.cbMute(self.getMuteList())
def unMute(self, clientId):
if clientId in self._mute:
del self._mute[clientId]
if clientId in self._clientData:
self._clientData[clientId].user.M = 0
net = self._clientData[clientId].user.NT
self.cbClient(net, self.getClientList(net))
self.cbMute(self.getMuteList())
def block(self, admin, clientId):
if clientId not in self._block:
self._block[clientId] = self.getClient(clientId).copy(AI=admin.ON)
if clientId in self._clientData:
net = self._clientData[clientId].user.NT
self.cbBlock(self.getBlockList())
def unBlock(self, clientId):
if clientId in self._block:
del self._block[clientId]
self.cbBlock(self.getBlockList())
def admin(self, clientId):
if clientId not in self._admin:
self._admin[clientId] = self.getClient(clientId).copy()
self.cbAdmin(self.getAdminList())
def unAdmin(self, clientId):
if clientId in self._admin:
del self._admin[clientId]
self.cbAdmin(self.getAdminList())
# vim: set et ai sw=4 ts=4 sts=4:

View File

@ -3,7 +3,7 @@
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com> # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
# See LICENSE.txt for copyright info # See LICENSE.txt for copyright info
from zope.interfaces import Interface from zope.interface import Interface
class IManager(Interface): class IManager(Interface):

View File

@ -3,7 +3,7 @@
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com> # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
# See LICENSE.txt for copyright info # See LICENSE.txt for copyright info
from zope.interfaces import implements from zope.interface import implements
from frn.manager import IManager from frn.manager import IManager
from frn.userstore.database import DatabaseUserStore from frn.userstore.database import DatabaseUserStore

View File

@ -3,7 +3,7 @@
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com> # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
# See LICENSE.txt for copyright info # See LICENSE.txt for copyright info
from zope.interfaces import implements from zope.interface import implements
from frn.manager import IManager from frn.manager import IManager
from twisted.internet import defer from twisted.internet import defer
from random import randint from random import randint

View File

@ -3,12 +3,56 @@
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com> # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
# See LICENSE.txt for copyright info # See LICENSE.txt for copyright info
from zope.interfaces import implements from zope.interface import implements
from twisted.internet.defer import Deferred, succeed
from frn.manager import IManager from frn.manager import IManager
from twisted.python import log from twisted.python import log
from frn.protocol.manager import FRNManagerClient, FRNManagerClientFactory from frn.protocol.manager import FRNManagerClient, FRNManagerClientFactory
class CustomManagerClientFactory(FRNManagerClientFactory):
def __init__(self, user, onConnect, onDisconnect):
self.user = user
self.onConnect = onConnect
self.onDisconnect = onDisconnect
self.authResult = False
self.client = None
self.managerReady = Deferred()
self.client = None
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)
class RemoteManager(object): class RemoteManager(object):
implements(IManager) implements(IManager)
@ -17,34 +61,39 @@ class RemoteManager(object):
self.reactor = reactor self.reactor = reactor
self.server = server self.server = server
self.port = port self.port = port
self.factory = FRNManagerClientFactory() self.factory = None
self.factory.continueTrying = 0 # FIXME
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): def serverLogin(self, user):
def connectionDone(conn): self.factory = CustomManagerClientFactory(
log.msg("%s connected" % self.server) user, self.onManagerConnect, self.onManagerDisconnect)
self.managerConnection = conn return self.doConnect()
return conn
self.reactor.connectTCP(self.server, self.port, self.factory)
log.msg("RemoteManager started connecting %s" % self.server)
return self.factory.managerConnection.addCallback(
connectionDone).addCallback(
lambda _: self.managerConnection.sendServerLogin(user))
def serverLogout(self, user): def serverLogout(self, user):
return self.managerConnection.sendServerLogout(user) if self.factory.client is not None:
return self.factory.client.sendServerLogout(user)
def clientLogin(self, user): def clientLogin(self, user):
return self.managerConnection.sendClientLogin(user) return self.factory.client.sendClientLogin(user)
def clientLogout(self, user): def clientLogout(self, user):
return self.managerConnection.sendClientLogout(user) return self.factory.client.sendClientLogout(user)
def getClientList(self): def getClientList(self):
return self.managerConnection.getClientList() return self.factory.client.getClientList()
def registerUser(self, user): def registerUser(self, user):
return self.managerConnection.registerUser(user) return self.factory.client.registerUser(user)
# vim: set et ai sw=4 ts=4 sts=4: # vim: set et ai sw=4 ts=4 sts=4:

View File

@ -15,10 +15,13 @@ from frn.utility import *
class FRNManagerClient(LineOnlyReceiver): class FRNManagerClient(LineOnlyReceiver):
PING_PERIOD = 3.0 # Seconds between ping requests
def connectionMade(self): def connectionMade(self):
log.msg("Connected to manager [%s]" % self.transport.getPeer().host) log.msg("Connected to manager [%s]" % self.transport.getPeer().host)
self.notifications = [] self.notifications = []
if not self.factory.managerConnection.called: # FIXME: Why??? if not self.factory.managerConnection.called: # FIXME: Why???
log.msg("Firing manager connection callback!")
self.factory.managerConnection.callback(self) self.factory.managerConnection.callback(self)
def connectionLost(self, reason): def connectionLost(self, reason):
@ -40,7 +43,7 @@ class FRNManagerClient(LineOnlyReceiver):
d.callback(result) d.callback(result)
def lineReceived(self, line): def lineReceived(self, line):
log.msg("notifications: %s" % str(self.notifications)) #log.msg("notifications: %s" % str(self.notifications))
if hasattr(self, 'serverlist'): if hasattr(self, 'serverlist'):
# TODO # TODO
pass pass
@ -50,13 +53,16 @@ class FRNManagerClient(LineOnlyReceiver):
def sendServerLogin(self, user): def sendServerLogin(self, user):
def loginDone(result): def loginDone(result):
self.managerdata = parseSimpleXML(result) self.managerdata = parseSimpleXML(result)
log.msg("Server login succeeded: %s" % str(self.managerdata)) log.msg("Server login results: %s" % str(self.managerdata))
if int(self.managerdata['mc']) > 2009004: if int(self.managerdata['mc']) > 2009004:
self.sendLine(responseToChallange( self.sendLine(responseToChallange(
self.managerdata['kp'])) self.managerdata['kp']))
self.pingtimer = LoopingCall(self.sendPing) if self.managerdata['al'] != '0':
self.pingtimer.start(3.0, False) self.transport.loseConnection()
self.factory.resetDelay() else:
self.pingtimer = LoopingCall(self.sendPing)
self.pingtimer.start(self.PING_PERIOD, False)
self.factory.resetDelay()
return self.managerdata return self.managerdata
log.msg("Sending server login") log.msg("Sending server login")
@ -98,7 +104,6 @@ class FRNManagerClientFactory(ReconnectingClientFactory):
def startFactory(self): def startFactory(self):
self.managerConnection = Deferred() self.managerConnection = Deferred()
ReconnectingClientFactory.startFactory(self)
class FRNManagerServer(LineOnlyReceiver): class FRNManagerServer(LineOnlyReceiver):

View File

@ -3,13 +3,13 @@
# Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com> # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
# See LICENSE.txt for copyright info # See LICENSE.txt for copyright info
from random import choice
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
from twisted.internet.protocol import ServerFactory from twisted.internet.protocol import ServerFactory
from twisted.protocols.policies import TimeoutMixin from twisted.protocols.policies import TimeoutMixin
from twisted.internet.task import LoopingCall from twisted.internet.task import LoopingCall
from twisted.python import log from twisted.python import log
from frn.user import FRNUser from frn.user import FRNUser
from frn.clienttracker import ClientTracker
from frn.protocol import versions from frn.protocol import versions
from frn.protocol.common import BufferingLineReceiver from frn.protocol.common import BufferingLineReceiver
from frn.utility import * from frn.utility import *
@ -34,22 +34,13 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
try: try:
self.pingTimer.stop() self.pingTimer.stop()
except AssertionError: pass except AssertionError: pass
try: if self.user is not None:
self.factory.clientList.remove(self) if self.user.ID:
self.factory.manager.clientLogout(self.user) log.msg("Logging out client %s" % self.user.ID)
self.factory.sendClientList([self.user.NT]) self.factory.manager.clientLogout(self.user)
except ValueError: pass self.factory.tracker.logout(self)
BufferingLineReceiver.connectionLost(self, reason) BufferingLineReceiver.connectionLost(self, reason)
def updateClient(self, **kw):
d = {}
for k, v in [(x.lower(), str(y)) for x,y in kw.items()]:
if self.user.get(k) != v:
d[k] = v
if len(d) > 0:
self.user.update(**d)
self.factory.sendClientList([self.user.NT])
def lineReceived(self, line): def lineReceived(self, line):
self.resetTimeout() self.resetTimeout()
sline = line.strip() sline = line.strip()
@ -59,20 +50,13 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
return return
else: else:
self.waitingKey = False self.waitingKey = False
if self.user.ID in self.factory.muteList: self.factory.tracker.login(self)
self.user.M = 1
else:
self.user.M = 0
self.user.S = 0
self.factory.clientList.append(self)
self.factory.sendClientList([self.user.NT]) # FIXME: older servers can't get here
self.sendNetworkList()
if self.role in ['OWNER', 'ADMIN']: if self.role in ['OWNER', 'ADMIN']:
self.sendMuteList() self.sendMuteList(self.factory.tracker.getMuteList())
self.sendBlockList() self.sendBlockList(self.factory.tracker.getBlockList())
if self.role == 'OWNER': if self.role == 'OWNER':
self.sendAccessFlags() self.sendAccessFlags(None)
self.sendAccessList() self.sendAccessList([])
self.pingCount += 1 self.pingCount += 1
self.pingTimer.start(0.5) self.pingTimer.start(0.5)
self.setTimeout(10.0) self.setTimeout(10.0)
@ -95,7 +79,7 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
handler(body) handler(body)
else: else:
self.unimplemented(command, body) self.unimplemented(command, body)
self.transport.loseConnection() # ??? #self.transport.loseConnection() # ???
def expectedReceived(self, data): def expectedReceived(self, data):
self.resetTimeout() self.resetTimeout()
@ -105,15 +89,23 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
def unimplemented(self, command, body): def unimplemented(self, command, body):
log.err("Unimplemented message: %s: %s" % (command, body)) log.err("Unimplemented message: %s: %s" % (command, body))
def getIndex(self):
return self.factory.tracker.getClientIndex(self.user.ID)+1
def authenticate(self, user): def authenticate(self, user):
def loginReturned(userId): def loginReturned(userId):
if userId != 'WRONG': if userId not in ['WRONG', 'DUPL']:
if self.factory.tracker.isBlocked(userId):
return ("BLOCK", userId)
return ("OK", userId) # FIXME: return OWNER or ADMIN eventually return ("OK", userId) # FIXME: return OWNER or ADMIN eventually
else: else:
return ("WRONG", "") return (userId, "")
user.IP = self.clientAddress.host user.IP = self.clientAddress.host
return self.factory.manager.clientLogin(user).addCallback(loginReturned) return self.factory.manager.clientLogin(user).addCallback(loginReturned)
def disconnect(self):
self.transport.loseConnection()
def decodeCT(self, body): def decodeCT(self, body):
def authReturned(result): def authReturned(result):
self.role, clientId = result self.role, clientId = result
@ -121,12 +113,10 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
if self.role == 'OK': if self.role == 'OK':
self.user = FRNUser(**body) self.user = FRNUser(**body)
self.user.ID = clientId self.user.ID = clientId
if self.role == 'OK':
if self.user.EA == self.factory.serverAuth.OW: if self.user.EA == self.factory.serverAuth.OW:
self.role = 'OWNER' self.role = 'OWNER'
elif self.user.EA in self.factory.adminList: elif self.factory.tracker.isAdmin(self.user.EA):
self.role = 'ADMIN' self.role = 'ADMIN'
# TODO: Blocklist
if versions.server > 2009004: if versions.server > 2009004:
self.waitingKey = True self.waitingKey = True
self.sendLine(str(versions.client)) self.sendLine(str(versions.client))
@ -146,7 +136,7 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
def decodeST(self, body): def decodeST(self, body):
log.msg("Set status = %d" % int(body)) log.msg("Set status = %d" % int(body))
self.updateClient(S=int(body)) self.factory.tracker.setStatus(self.user.ID, int(body))
def decodeTM(self, body): def decodeTM(self, body):
log.msg("TM: %s" % str(body)) log.msg("TM: %s" % str(body))
@ -154,30 +144,55 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
msgtype = 'A' msgtype = 'A'
else: else:
msgtype = 'P' msgtype = 'P'
for c in self.factory.clientList: for c in self.factory.tracker.getClientList(self.user.NT):
if msgtype == 'A' or c.user.ID == body['id']: if msgtype == 'A' or c.ID == body['id']:
if c != self: if c.ID != self.user.ID:
c.sendTextMessage(self.user.ID, body['ms'], msgtype) client = self.factory.tracker.getClientProtocol(c.ID)
client.sendTextMessage(self.user.ID, body['ms'], msgtype)
def decodeTX(self, body): def decodeTX(self, body):
if body == '0': # FIXME: Mute? if body == '0':
log.msg("TX0") if not self.factory.tracker.isMute(self.user.ID):
clientIdx = self.factory.clientList.index(self)+1 ih,il = divmod(self.getIndex(), 256)
ih,il = divmod(clientIdx, 256) self.transport.write(chr(1)+chr(ih)+chr(il))
self.transport.write(chr(1)+chr(ih)+chr(il))
elif body == '1': elif body == '1':
log.msg("TX1") if self.pingTimer.running:
self.pingTimer.stop()
self.expectRawData(325) self.expectRawData(325)
if self.pingTimer.running:
self.pingTimer.stop() def decodeMC(self, body):
if self.role in ["OWNER","ADMIN"]:
self.factory.tracker.mute(self.user, body['ip'])
def decodeUM(self, body):
if self.role in ["OWNER","ADMIN"]:
self.factory.tracker.unMute(body['ip'])
def decodeBC(self, body):
if self.role in ["OWNER","ADMIN"]:
self.factory.tracker.block(self.user, body['ip'])
self.factory.tracker.getClientProtocol(body['ip']).disconnect()
def decodeUC(self, body):
if self.role in ["OWNER","ADMIN"]:
self.factory.tracker.unBlock(body['ip'])
def decodeAA(self, body):
if self.role == "OWNER":
self.factory.tracker.admin(body['ip'])
def decodeDA(self, body):
if self.role == "OWNER":
self.factory.tracker.unAdmin(body['ip'])
def audioFrameReceived(self, frame): def audioFrameReceived(self, frame):
log.msg("audioFrameReceived") #log.msg("audioFrameReceived")
clientIdx = self.factory.clientList.index(self)+1 if not self.factory.tracker.isMute(self.user.ID):
for c in self.factory.clientList: clientIdx = self.getIndex()
if int(c.user.S) < 2 and c != self: for c in self.factory.tracker.getClientList(self.user.NT):
log.msg("Sending to %s" % c.user.ON) if int(c.S) < 2 and c.ID != self.user.ID:
c.sendAudioFrame(clientIdx, frame) #log.msg("Sending to %s" % c.ON)
self.factory.tracker.getClientProtocol(c.ID).sendAudioFrame(clientIdx, frame)
def sendPing(self): def sendPing(self):
if self.pingCount > 20: if self.pingCount > 20:
@ -197,32 +212,42 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
)) ))
self.pingCount += 1 self.pingCount += 1
def sendNetworkList(self): def sendNetworkList(self, networks):
log.msg("Send network list") log.msg("Send network list")
self.transport.write(chr(5)) self.transport.write(chr(5))
nets = self.factory.getNetworkList() self.sendLine(str(len(networks)))
self.sendLine(str(len(nets))) for net in networks:
for net in nets:
self.sendLine(net) self.sendLine(net)
self.pingCount += 1 self.pingCount += 1
def sendMuteList(self): def sendMuteList(self, clients):
log.msg("Sending mute list to %s: %s" % (self.user.ON, str(clients)))
self.transport.write(chr(9)) self.transport.write(chr(9))
self.sendLine('0') # TODO self.sendLine(str(len(clients)))
for c in clients:
self.sendLine(c.asXML('AI','NN','CT','BC','ON','ID'))
def sendBlockList(self): def sendBlockList(self, clients):
log.msg("Sending block list to %s: %s" % (self.user.ON, str(clients)))
self.transport.write(chr(8)) self.transport.write(chr(8))
self.sendLine('0') # TODO self.sendLine(str(len(clients)))
for c in clients:
self.sendLine(c.asXML('AI','NN','CT','BC','ON','ID'))
def sendAdminList(self): def sendAdminList(self, clients):
log.msg("Sending admin list to %s: %s" % (self.user.ON, str(clients)))
self.transport.write(chr(6)) self.transport.write(chr(6))
self.sendLine('0') # TODO self.sendLine(str(len(clients)))
for c in clients:
self.sendLine(c.asXML('NN','CT','BC','ON','ID'))
def sendAccessList(self): def sendAccessList(self, clients):
self.transport.write(chr(7)) self.transport.write(chr(7))
self.sendLine('0') # TODO self.sendLine(str(len(clients)))
for c in clients: # FIXME
self.sendLine(c.asXML('AI','NN','CT','BC','ON','ID'))
def sendAccessFlags(self): def sendAccessFlags(self, flags):
self.transport.write(chr(10)) self.transport.write(chr(10))
self.sendLine('2') # TODO self.sendLine('2') # TODO
self.sendLine('o') self.sendLine('o')
@ -251,11 +276,11 @@ class FRNServerFactory(ServerFactory):
self.manager = manager self.manager = manager
self.serverAuth = serverAuth self.serverAuth = serverAuth
self.talking = None self.talking = None
self.clientList = []
self.adminList = []
self.muteList = []
self.blockList = []
self.officialNets = [] self.officialNets = []
self.tracker = ClientTracker(
self.sendClientList, self.sendNetworkList,
self.sendMuteList, self.sendBlockList,
self.sendAdminList)
def startFactory(self): def startFactory(self):
ServerFactory.startFactory(self) ServerFactory.startFactory(self)
@ -265,24 +290,29 @@ class FRNServerFactory(ServerFactory):
self.manager.serverLogout(self.serverAuth) self.manager.serverLogout(self.serverAuth)
ServerFactory.stopFactory(self) ServerFactory.stopFactory(self)
def getNetworkList(self): def sendNetworkList(self, networks):
n = set([c.user.NT for c in self.clientList]) nets = self.officialNets+list(set(networks) - set(self.officialNets))
o = set(self.officialNets) for c in self.tracker.getClientList():
return self.officialNets+list(n-o) self.tracker.getClientProtocol(c.ID).sendNetworkList(nets)
def sendNetworkList(self): def sendClientList(self, network, clients):
n = self.getNetworkList() for c in clients:
for c in self.clientList: self.tracker.getClientProtocol(c.ID).sendClientList(clients)
c.sendNetworkList(n)
def sendMuteList(self, clients):
for c in self.tracker.getClientList():
if self.tracker.isAdmin(c.ID) or c.EA == self.serverAuth.OW:
self.tracker.getClientProtocol(c.ID).sendMuteList(clients)
def sendBlockList(self, clients):
for c in self.tracker.getClientList():
if self.tracker.isAdmin(c.ID) or c.EA == self.serverAuth.OW:
self.tracker.getClientProtocol(c.ID).sendBlockList(clients)
def sendAdminList(self, clients):
for c in self.tracker.getClientList():
if c.EA == self.serverAuth.OW:
self.tracker.getClientProtocol(c.ID).sendAdminList(clients)
def sendClientList(self, networks=[]):
n = {}
for c in self.clientList:
l = n.get(c.user.NT, [])
l.append(c.user)
n[c.user.NT] = l
for c in self.clientList:
if (not networks) or (c.user.NT in networks):
c.sendClientList(n[c.user.NT])
# vim: set et ai sw=4 ts=4 sts=4: # vim: set et ai sw=4 ts=4 sts=4:

View File

@ -25,7 +25,7 @@ class FRNUser(object):
self.set(attr, value) self.set(attr, value)
def __str__(self): def __str__(self):
return asXML(self) return self.asXML()
def __repr__(self): def __repr__(self):
return "FRNUser(%s)" % \ return "FRNUser(%s)" % \
@ -52,6 +52,11 @@ class FRNUser(object):
for field, value in kw.items(): for field, value in kw.items():
self.set(field, value) self.set(field, value)
def copy(self, **kw):
n = FRNUser(**self._fields)
n.update(**kw)
return n
def updateXML(self, xml): def updateXML(self, xml):
self.update(dict(parseSimpleXML(xml))) self.update(dict(parseSimpleXML(xml)))

View File

@ -19,7 +19,7 @@ if __name__ == '__main__':
def standardManagerFactory(): def standardManagerFactory():
log.msg("Building Manager") log.msg("Building Manager")
return RemoteManager(reactor, '83.82.28.221') return RemoteManager(reactor)
reactor.listenTCP(10025, FRNManagerServerFactory( reactor.listenTCP(10025, FRNManagerServerFactory(
# DatabaseUserStore( # DatabaseUserStore(

View File

@ -46,8 +46,8 @@ if __name__ == '__main__':
# DatabaseUserStore( # DatabaseUserStore(
# ConnectionPool("sqlite3", "frn_users.sqlite3", # ConnectionPool("sqlite3", "frn_users.sqlite3",
# check_same_thread=False)), # check_same_thread=False)),
# RemoteManager(reactor, '83.82.28.221'), RemoteManager(reactor),
DummyManager(), # DummyManager(),
FRNUser( FRNUser(
SN=server,PT=port, SN=server,PT=port,
BN=backup_server, BP=backup_port, BN=backup_server, BP=backup_port,