Skip to content

Instantly share code, notes, and snippets.

/benchmark Secret
Created Apr 3, 2013

Embed
What would you like to do?
comnet
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import socket
import time
import sys
count = range(100000)
letter = str(sys.argv[1])
print(letter)
register = bytes(':{0}:control::register:{0}\r\n.\r\n'.format(letter), 'UTF-8')
pong = bytes(':{0}:{0}:alarm:ping\r\n.\r\n'.format(letter), 'UTF-8')
s = socket.socket()
s.connect(('127.0.0.1', 8081))
s.send(register)
values = []
for i in count:
time.sleep(0)
start = time.time()
s.send(pong)
s.recv(1024)
end = time.time()
diff = start - end
print(('time:', diff))
values.append(diff)
i = 0
for var in values:
i += var
average = i / len(values) #seconds
miliseconds = average*1000
print(('average: ', miliseconds, 'ms'))
# -*- coding: utf-8 -*-
import socket
import sys
letter = str(sys.argv[1])
print(letter)
register = bytes(':{0}:control::register:{0}\r\n.\r\n'.format(letter), 'UTF-8')
pong = bytes(':{0}:{0}:walnut:pong\r\n.\r\n'.format(letter), 'UTF-8')
s = socket.socket()
s.connect(('127.0.0.1', 8081))
s.send(register)
while True:
s.recv(1024)
s.send(pong)
import pyuv
import socket
import local
import protocol
from message import Message
class Connection(pyuv.TCP):
"""class which represents single connection, can be useful"""
terminator = protocol.message_terminator
def __init__(self, server):
"""init, shall we?"""
self.ibuffer = ""
self._callback = lambda x: None
self._error_callback = lambda: None
super(Connection, self).__init__(server.loop)
def setCallback(self, callback=None):
""" sets the connection callback on incoming message"""
if callback is not None:
self._callback = callback
else:
self._callback = lambda x: None
def setErrorCallback(self, callback=None):
""" sets the connection callback on incoming message"""
if callback is not None:
self._error_callback = callback
else:
self._error_callback = lambda: None
def startup(self):
""" stars read incoming data"""
self.start_read(self.on_read)
def on_read(self, client, data, error):
""" everytime the reading starts!"""
if data is None:
self._error_callback()
return
data = data.decode("UTF-8")
searched = self.ibuffer[:-len(self.terminator)] + data
while True:
splitted = searched.split(self.terminator, 1)
if len(splitted) == 2:
self.ibuffer += splitted[0]
#print(("comnet","recv" ,self.ibuffer))
self._callback(self.ibuffer)
self.ibuffer = ""
searched = data = splitted[1]
else:
self.ibuffer += data
break
def displace(self, message):
""" displaces the message"""
#print(("comnet", "send", str(message)))
self.write(bytes(str(message) + self.terminator, "UTF-8"))
class Server(pyuv.TCP):
"""basic class for handling comnets server"""
def __init__(self, addr, manager, loop):
""" we innit it, don't we? also adding host and port is not bad"""
super(Server, self).__init__(loop)
self.manager = manager
self.ip, self.port = addr
self.bind(addr)
self.shakers = []
self.conteiners = {}
self.listen(self.handle_accept)
def dial_connection(self, ip):
""" creates new connection and returns it"""
connection = Connection(self)
addr = (ip, self.port)
def after_dial(tcp_handle, error):
self.create_handshaker(tcp_handle)
connection.connect(addr, after_dial)
def handle_accept(self, server, error):
"""method to accept new connection"""
connection = Connection(self)
self.accept(connection)
self.create_handshaker(connection)
def create_handshaker(self, connection):
shaker = Handshaker(connection,
self.handshake_done,
self.handshake_error)
self.shakers.append(shaker)
def handshake_error(self, shaker):
shaker.stop_read()
self.shakers.remove(shaker)
def handshake_done(self, shaker):
""" after handshake is done, extracts connection and name from
Handshaker, removes it and creates Communicator object """
print(("comnet", "handshaker", "handshaking done, moving connection"
"to Communicator object"))
self.shakers.remove(shaker)
connection = shaker.connection
name = shaker.name
try:
conteiner = self.conteiners[name]
except KeyError:
conteiner = self.manager.create_conteiner()
self.conteiners[name] = conteiner
com = Communicator(connection)
conteiner.add_communicator(com)
class Point():
""" Class to manage connections to different points by the context """
def __init__(self, server, manager):
""" we need object with actual connection"""
self.server = server
self.conteiners = server.conteiners
self.manager = manager
def displace(self, message):
self.conteiners[message.target_point].displace(message)
def on_read(self, conteiner, message):
if message.target_point == protocol.point_name:
self.manager.displace_to_localhost(message)
else:
self.displace(message)
def remove_conteiner(self, conteiner):
for name, con in self.conteiners.items():
if con == conteiner:
todel = name
del self.conteiners[todel]
class Conteiner():
def __init__(self, point):
self.communicators = []
self.point = point
def add_communicator(self, com):
self.communicators.append(com)
com.setCallback(self.on_read)
com.setErrorCallback(self.on_error)
def displace(self, message):
self.communicators[0].displace(message)
def on_error(self, com):
self.communicators.remove(com)
if len(self.communicators) == 0:
self.point.remove_conteiner(self)
def on_read(self, message):
self.point.on_read(self, message)
class Handshaker():
""" executes handshaking process on given connection """
def __init__(self, connection, callback, error_callback):
""" needs the connection on which handshaking should be done and
callback to call after its done:
callback(handshaker)"""
self.connection = connection
self.error_callback = error_callback
self.callback = callback
self.protocol = protocol.Handshaker(self)
self.tasks = self.protocol.tasks[::-1]
connection.setCallback(self.recv)
self.make_shake()
self.connection.startup()
def make_shake(self):
if len(self.tasks) == 0:
self.callback(self)
return
name, send, recv = self.tasks.pop()
self.connection.displace(name + ":" + send())
self.wait_for = name, recv
def recv(self, data):
l = data.split(":", 1)
name, recv = self.wait_for
if len(l) < 2:
self.connection.displace("error: bad syntax")
return
if l[0] not in ("error", name):
self.connection.displace("error: bad item")
return
if l[0] == "error":
self.error_callback(self)
elif l[0] == name:
try:
recv(l[1])
except protocol.protocolError as err:
mes = "error:{0}:{1}".format(err.string_name, str(err))
self.connection.displace(mes)
self.error_callback(self)
else:
self.make_shake()
else:
print("shit happend")
class Communicator():
def __init__(self, con):
self.connection = con
self._callback = lambda x: None
self._error_callback = lambda: None
self.connection.setCallback(self.on_read)
self.connection.setErrorCallback(self.on_error)
def displace(self, message):
self.connection.displace(message)
def on_read(self, string):
message = Message(protocol.decode_message(string), self)
self._callback(message)
def on_error(self):
self._error_callback(self)
def setErrorCallback(self, callback=None):
""" sets the connection callback on incoming message"""
if callback is not None:
self._error_callback = callback
else:
self._error_callback = lambda: None
def setCallback(self, callback=None):
""" sets the connection callback on incoming message"""
if callback is not None:
self._callback = callback
else:
self._callback = lambda x: None
class Manager():
""" class used to manage the comnet server"""
def __init__(self, addr, local_addr, broadcast_addr, loop):
""" init shoudln't we?'"""
self.server = Server(addr, self, loop)
self.point = Point(self.server, self)
self.broadcaster = Broadcaster(broadcast_addr, loop, self)
self.local = local.Manager(local_addr, self, loop)
def dial_connection(self, ip, name):
""" dials connection to specified adress and name"""
self.server.dial_connection(ip)
def allow_connect(self, name):
""" allows specified point to connect via broadcaster"""
self.broadcaster.allow_connect(name)
def displace_to_comnet(self, message):
""" sends message to comnet"""
self.point.displace(message)
def displace_to_localhost(self, message):
self.local.displace_to_localhost(message)
def create_conteiner(self):
return Conteiner(self.point)
class Broadcaster:
""" this is little bit tricky, I couldn't find a way to force pyuv bindigs
to crate broadcaster ... maybe it is possible, but I coudln't find a
way to do it, so here is version where I use nonblocking standart socket
combined with libuv's Timer object to create "async" behavior, the
delay before this class is able to detect incoming broadcasting
shoudln't be so much deal anyway and for outgoing it's the same, on the
other hand for effectivity there will be two timers for that purpose,
one for incoming and one for outgoing"""
def __init__(self, addr, loop, manager):
"""we need the loop and adress on which we should work"""
self.ip, self.port = addr
self.manager = manager
self.ignored = []
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
self.socket.setblocking(0)
self.socket.bind(addr)
self.outgoing_timer = pyuv.Timer(loop)
self.outgoing_timer.start(self.outgoing, 1, 1)
self.incoming_timer = pyuv.Timer(loop)
self.incoming_timer.start(self.incoming, 1, 1)
def outgoing(self, timer_handle):
""" method designed to broadcast the point informations"""
items = ("comnet", socket.gethostname())
mes = ":".join(items)
self.socket.sendto(bytes(mes, "UTF-8"), ('<broadcast>', self.port))
def incoming(self, timer_handle):
""" receives incoming broadcasts"""
try:
mes, addr = self.socket.recvfrom(8192)
ip, port = addr
items = mes.decode("UTF-8").split(":", 1)
if len(items) == 2 and items[0] == "comnet":
if items[1] not in self.ignored:
self.manager.dial_connection(ip, items[1])
self.ignored.append(items[1])
except socket.error:
# TODO: check if it's only error when recvfrom is empty
pass
def allow_connect(self, name):
""" allows connection of name"""
self.ignored.remove(name)
# -*- coding: utf-8 *-*
import pyuv
import control
from message import Message, Error_message, Empty_error_message
import protocol
"""
message syntax:
<source point>:<source channel>:<target channel>:<target point>:<message>
"""
class rightsError(Exception):
"""class used to when problem with rights"""
class noRegisteredError(Exception):
"""used when channel is notRegistered"""
class alreadyRegisteredError(Exception):
"""used when channel is already registered"""
class messageLengthError(Exception):
"""used when incoming message is too long"""
class channelLockedError(Exception):
"""used when channel is locked"""
class Connection(pyuv.TCP):
"""class which represents single connection, can be useful"""
maxMessageLength = 16384
terminator = protocol.message_terminator
def __init__(self, server, manager):
"""init, shall we?"""
super(Connection, self).__init__(server.loop)
self.ibuffer = ""
self.manager = manager
def on_read(self, client, data, error):
""" everytime the reading starts!"""
if data is None:
self.manager.remove_connection(self)
return
data = data.decode("UTF-8")
searched = self.ibuffer[:-len(self.terminator)] + data
while True:
splitted = searched.split(self.terminator, 1)
if len(splitted) == 2:
self.ibuffer += splitted[0]
self.found_terminator()
searched = data = splitted[1]
else:
self.ibuffer += data
break
def displace(self, message):
"""little moddification to standart push"""
#print(("local", "sends", str(message)))
self.write(bytes(str(message) + self.terminator, "UTF-8"))
def check_max_length(self, string):
"""checks maximal length of one message"""
if len(string) > self.maxMessageLength:
string = ("Message is too long, please make it"
" shorter, max length is {0}")
raise messageLengthError(string.format(self.maxMessageLength))
def create_message_from_string(self, string):
"""create message object from the string"""
return Message(protocol.decode_message(string), self)
def found_terminator(self):
"""found end of message"""
string = self.ibuffer.strip()
self.ibuffer = ""
try:
self.check_max_length(string)
except messageLengthError as error:
error = Empty_error_message(str(error))
self.displace(error)
return
try:
message = self.create_message_from_string(string)
except protocol.messageSyntaxError as error:
error = Empty_error_message(str(error))
self.displace(error)
self.manager.displace_from_local(message)
class Server(pyuv.TCP):
"""basic class for handling local connecitons server"""
connections = []
def __init__(self, addr, manager, loop):
""" we innit it, don't we? also adding host and port is not bad"""
super(Server, self).__init__(loop)
self.bind(addr)
self.listen(self.handle_accept)
self.manager = manager
def handle_accept(self, server, error):
"""method to accept new connection"""
connection = Connection(self, self.manager)
self.accept(connection)
connection.start_read(connection.on_read)
self.connections.append(connection)
class Manager():
"""class to manage the local server"""
def __init__(self, addr, comnet, loop):
"""init shoudln't we? local is object which represents local
connections and comnet should represent connection to the comnet'"""
self.channels = {}
self.loop = loop
self.comnet = comnet
self.server = Server(addr, self, loop)
self.control = control.control(self, comnet)
self.register('control', self.control)
def displace_from_local(self, message):
""" used to displace messages coming from clients"""
try:
self.check_source_channel_rights(message)
except (rightsError, noRegisteredError) as error:
error = Error_message(message, str(error))
message.source.displace(error)
return
# let's decide the direction, comnet or localhost?
if message.target_point in ("", "localhost"):
self.displace_to_localhost(message)
else:
self.displace_to_comnet(message)
def displace_to_localhost(self, message):
"""sends message to client connection"""
try:
self.check_if_channel_exists(message.target_channel)
except noRegisteredError:
error = Error_message(message, "target_channel is not registered!")
message.source.displace(error)
return
try:
self.check_if_locked(message.target_channel)
except channelLockedError:
error = Error_message(message, "targe_channel is locked!")
message.source.displace(error)
return
self.channels[message.target_channel].connection.displace(message)
def displace_to_comnet(self, message):
""" sends message from local object to comnet object"""
message.source_point = protocol.point_name
self.comnet.displace_to_comnet(message)
def check_if_locked(self, channel):
"""raises channelLockedError if the channel is locked"""
if self.channels[channel].lock:
raise channelLockedError
def check_if_channel_exists(self, channel):
"""checks if the <channel> exists"""
try:
self.channels[channel]
except KeyError:
raise noRegisteredError
def register(self, name, connection):
"""registers the channel for specific connection,
TRUE if succeed, FALSE if taken"""
try:
self.channels[name]
except KeyError:
channel = Channel(name)
channel.connection = connection
self.channels[name] = channel
print("channel registered")
return name
else:
print("channel failed to register")
raise alreadyRegisteredError
def check_source_channel_rights(self, message):
"""method to check if message can be sent by connection"""
try:
connection = self.channels[message.source_channel].connection
if connection == message.source:
return message
else:
if message.target_channel == "control":
print("targeted channel is system 'control' channel")
return message
print("Channel is owned by different connection")
message = "Your source_channel is not yours!"
raise rightsError(message)
except KeyError:
if message.target_channel == "control":
print("targeted channel is system 'control' channel")
return message
print("Channel is not owned by the connection or any")
message = "Your source_channel is not yours and registered"
raise noRegisteredError(message)
def lock_channel(self, message, name):
""" locks channel, needs the source message to confirm rights"""
try:
channel = self.channels[name]
except KeyError:
raise noRegisteredError
return
if message.source == channel.connection:
channel.lock = True
else:
raise rightsError
return
class Channel():
"""class represents channel in local comnet server"""
name = ""
connection = None
lock = False
def __init__(self, name):
"""init!"""
self.name = name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.