|
- # -*- coding: utf-8 -*-
- #
- # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
- # See LICENSE.txt for copyright info
-
- from twisted.application.service import MultiService
- from zope.interface import implements
- from twisted.plugin import IPlugin
- from twisted.application.service import IServiceMaker
- from twisted.application import internet
- from twisted.python import usage
- from ConfigParser import ConfigParser
- from frn.protocol.client import FRNClient, FRNClientFactory
- from frn.user import FRNUser
- from twisted.python import log
- from os.path import curdir, join as pjoin
-
- cType = {'PC Only': 'O', 'Crosslink': 'C', 'Parrot': 'P'}
- cStatus = {'0': 'T', '1': 'R', '2': 'N'}
-
- clients = []
- talking = None
-
- class FRNCrosslinkClient(FRNClient):
-
- def connectionMade(self):
- self.txOk = False
- self.txReq = False
- self.clientId = None
- from twisted.internet import reactor
- self.reactor = reactor
- FRNClient.connectionMade(self)
-
- def getClientName(self, client_id):
- if self.clientsById.has_key(client_id):
- return self.clientsById[client_id]['on']
- else:
- return client_id
-
- def textMessageReceived(self, client, message, target):
- global clients
- if target == 'A':
- msg = "[%s] %s" % (self.getClientName(client), message)
- if client != self.clientId:
- for _, _, _, factory in clients:
- if factory != self.factory:
- factory.connection.sendTextMessage('', msg)
- else:
- if message.startswith('!'):
- cmd = message[1:]
- if cmd == "who":
- for server, port, u, factory in clients:
- cl = []
- cl.append("<u>%s@%s:%d</u>" % (u.NT,server,port))
- for c in factory.connection.clients:
- ss = cStatus.get(c['s'], '?')
- if c['m'] != '0':
- ss = ss.lower()
- cl.append(" %s%s %s " % (
- cType.get(c['bc'], 'G'),
- ss,
- c['on'].replace('<', '<'),
- ))
- sm = [cl[i*15:(i+1)*15]
- for i in range((len(cl)+14)/15)]
- for m in sm:
- reply = '<br>'.join(m)
- self.sendTextMessage(client, reply)
-
- def decodeTX(self, my_id):
- log.msg("Got TX ack for %s" % self.user.ON)
- self.txOk = True
-
- def stopTransmission(self):
- FRNClient.stopTransmission(self)
- log.msg("Stopped TX on %s" % self.user.ON)
-
- def goIdle(self):
- global talking
- self.txReq = False
- self.txOk = False
- talking = None
- self.stopTransmission()
-
- def audioFrameReceived(self, from_id, frames):
- global clients, talking
- if talking is None or talking == self:
- talking = self
- for _, _, _, factory in clients:
- conn = factory.connection
- if conn != self:
- role = conn.serverdata.get('al', None)
- if role in ['OK', 'ADMIN', 'OWNER']:
- if conn.txOk:
- conn.txReq = False
- conn.sendAudioFrame(frames)
- conn.busyTimer.reset(2.0)
- else:
- if not conn.txReq:
- log.msg("Requesting TX for %s" % conn.user.ON)
- conn.startTransmission()
- conn.txReq = True
- conn.busyTimer = self.reactor.callLater(
- 5.0, conn.goIdle)
- self.pong()
-
- def loginResponse(self, info):
- log.msg("%s login: %s" % (self.user.ON, info['al']))
-
- def clientsListUpdated(self, clients):
- self.clients = clients
- self.clientsById = dict([(i['id'], i) for i in clients])
- if self.clientId is None:
- for c in clients:
- if c['on'] == self.user.ON and c['bc'] == self.user.BC:
- self.clientId = c['id']
-
- class FRNCrosslinkClientFactory(FRNClientFactory):
- protocol = FRNCrosslinkClient
-
- def buildProtocol(self, addr):
- p = FRNClientFactory.buildProtocol(self, addr)
- self.connection = p
- return p
-
-
- class Options(usage.Options):
-
- optParameters = [
- ["confdir", "c", curdir, "Directory containing config files"]
- ]
-
- def parseArgs(self, *serverdefs):
- basedir = self['confdir']
- acfg = ConfigParser()
- acfg.read(['/etc/grn/accounts.conf',
- pjoin(basedir,'accounts.conf'), 'accounts.conf'])
-
- scfg = ConfigParser()
- scfg.read(['/etc/grn/servers.conf',
- pjoin(basedir,'servers.conf'), 'servers.conf'])
-
- clients = []
- for serverdef in serverdefs:
- account_name, server_name, network_name = serverdef.split(':', 2)
-
- sd = {}
- sd['server'] = scfg.get(server_name, 'server')
- sd['port'] = scfg.getint(server_name, 'port')
- sd['backup_server'] = scfg.get(server_name, 'backup_server')
- sd['backup_port'] = scfg.getint(server_name, 'backup_port')
- sd['operator'] = acfg.get(account_name, 'operator')
- sd['email'] = acfg.get(account_name, 'email')
- sd['password'] = acfg.get(account_name, 'password')
- sd['description'] = acfg.get(account_name, 'description')
- sd['country'] = acfg.get(account_name, 'country')
- sd['city'] = acfg.get(account_name, 'city')
- sd['network'] = network_name
- clients.append(sd)
- self['clients'] = clients
-
-
- class FRNCrosslinkServiceMaker(object):
- implements(IServiceMaker, IPlugin)
- tapname = "frncrosslink"
- description = "Freeradionetwork crosslink"
- options = Options
-
- def makeService(self, options):
- s = MultiService()
- global clients # FIXME: Get rid of this hack
- for c in options['clients']:
- user = FRNUser(
- EA=c['email'],
- PW=c['password'], ON=c['operator'],
- # BC=c['transmission'], DS=c['description'],
- BC="Crosslink", DS=c['description'],
- NN=c['country'], CT=c['city'], NT=c['network'])
- factory = FRNCrosslinkClientFactory(user)
- clients.append((c['server'], c['port'], user, factory))
- s.addService(
- internet.TCPClient(c['server'], c['port'], factory))
- return s
-
-
- serviceMaker = FRNCrosslinkServiceMaker()
-
- # vim: set et ai sw=4 ts=4 sts=4:
|