Skip to content

Instantly share code, notes, and snippets.

@sakekasi
Created March 10, 2014 05:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sakekasi/9460002 to your computer and use it in GitHub Desktop.
Save sakekasi/9460002 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
from twisted.internet import protocol, reactor
from twisted.internet.endpoints import TCP4ClientEndpoint, TCP4ServerEndpoint
from twisted.protocols.basic import LineReceiver
from functools import partial
from time import strftime, localtime, gmtime
import datetime
import parse
import respond
host = "127.0.0.1"
ports = {
'Farmar': 12600,
'Gasol': 12601,
'Hill': 12602,
'Meeks': 12603,
'Young': 12604
}
talks = {
'Farmar': ['Meeks','Young'],
'Gasol': ['Meeks','Young'],
'Hill': ['Meeks'],
'Meeks': ['Farmar', 'Gasol', 'Hill'],
'Young': ['Farmar', 'Gasol']
}
class Tweets(LineReceiver):
def __init__(self, fact, fp):
self.factory = fact
self.fp = fp
iamat = respond.iamat
whatsat = respond.whatsat
at = respond.at
invalid = respond.invalid
def connectionMade(self):
self.fp.write("NEW CONNECTION AT " +\
strftime('%Y-%m-%d %H:%M:%S', localtime()) + ' ' +\
"\n")
self.fp.flush()
def lineReceived(self, line):
self.fp.write(line+'\n')
self.fp.flush()
print 'got '+line
cmd = parse.parse_message(line)
resp = {'IAMAT': partial(self.iamat, cmd),
'WHATSAT': partial(self.whatsat, cmd),
'AT': partial(self.at, cmd),
'?': partial(self.invalid, cmd)
}.get(cmd['type'])()
self.fp.write(resp)
self.fp.flush()
self.transport.write(resp)
def connectionLost(self, reason):
self.fp.write("CONNECTION CLOSED AT " +\
strftime('%Y-%m-%d %H:%M:%S', localtime())+\
"\n")
self.fp.flush()
class TweetsFactory(protocol.Factory):
stored_iamats = {}
def __init__(self, name):
self.name = name
self.talks = talks[name]
self.port = ports[name]
self.clients = []
def getClients(self, callback):
endpoints = map(lambda n: TCP4ClientEndpoint(reactor, host,
ports[n]), self.talks)
conns = map(lambda p: p.connect(ProxyFactory), endpoints)
for c in conns:
c.addCallback(callback)
return conns
def clientSendMessage(self, line):
conns = self.getClients(partial(clientCallback, line))
return conns
def startFactory(self):
self.fp = open(self.name, 'a')
def buildProtocol(self, addr):
return Tweets(self, self.fp)
def stopFactory(self):
self.fp.close()
class Proxy(protocol.Protocol):
def sendMessage(self, line):
print 'sending '+line
reactor.callFromThread(self.transport.write, line)
ProxyFactory = protocol.ClientFactory()
ProxyFactory.protocol = Proxy
def clientCallback(line, client):
client.sendMessage(line)
client.transport.loseConnection()
def serv_fact(name):
factory = TweetsFactory(name)
return factory.port, factory
def shutdown(ignored):
reactor.stop()
if __name__ == '__main__':
for k in ports:
factory = serv_fact(k)
endpoint = TCP4ServerEndpoint(reactor, factory[0])
endpoint.listen(factory[1]).addErrback(shutdown)
reactor.run()
from functools import partial
from schemas import *
def parse_schema(schema, cmd_type, toks, inv):
command = {}
if len(toks) != len(schema):
return inv()
command['type'] = cmd_type
for i in range(len(schema)):
try:
command[schema[i][0]] = schema[i][1](toks[i])
except ValueError:
return inv()
return command
def invalid(line):
return {'type': '?', 'data': line}
def parse_message(line):
toks = line.split()
inv = partial(invalid, line)
return {'IAMAT': partial(iamat, toks[1:], inv),
'WHATSAT': partial(whatsat, toks[1:], inv),
'AT': partial(at, toks[1:], inv),
}.get(toks[0], inv)()
iamat = partial(parse_schema, iamat_schema, 'IAMAT')
whatsat = partial(parse_schema, whatsat_schema, 'WHATSAT')
at = partial(parse_schema, at_schema, 'AT')
from twisted.internet import threads
from time import time
from functools import partial
from schemas import *
def iamat(self, cmd):
cmd['srv_name'] = self.factory.name
cmd['time_diff'] = time() - cmd['timestamp']
rcmd = cmd.copy()
rcmd['type'] = 'AT'
if(cmd['timestamp'] > self.factory.stored_iamats\
.get(cmd['client_id'], {'timestamp':0.00})\
.get('timestamp')):
self.factory.stored_iamats[cmd['client_id']] = rcmd
ds = self.factory.clientSendMessage(flatten_cmd(at_schema, rcmd))
return flatten_cmd(at_schema, rcmd)
def whatsat(self, cmd):
pass
def at(self, cmd):
if cmd['srv_name'] in self.factory.talks:
rcmd = cmd.copy()
rcmd['srv_name'] = self.factory.name
if( cmd['timestamp'] > self.factory.stored_iamats\
.get(cmd['client_id'], {'timestamp':0.00})\
.get('timestamp')):
self.factory.stored_iamats[cmd['client_id']] = cmd
ds = self.factory.clientSendMessage(flatten_cmd(at_schema, rcmd))
return flatten_cmd(at_schema, rcmd)
else:
cmd['data'] = flatten_cmd(at_schema, cmd)
cmd['type'] = '?'
return invalid(cmd)
def invalid(self, cmd):
return flatten_cmd(invalid_schema, cmd)
def flatten_cmd(schema, cmd):
ret = cmd['type']
for x in schema:
k = x[0]
ret = ret + ' ' + str(cmd[k])
return ret+'\n'
iamat_schema = [('client_id', str), ('lat', float), ('long', float), ('timestamp', float)]
whatsat_schema = [('client_id', str), ('radius', float), ('upper_bound', int)]
at_schema = [('srv_name', str), ('time_diff', float)]+iamat_schema
invalid_schema = [('data', str)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment