class PluginManager(EventManager): def __init__(self, controller): super(PluginManager, self).__init__(controller) self.load_plugins() try: config = self.controller.config_file.items('router') except NoSectionError: config = {} zmq_factory = ZmqFactory() sub_endpoint = ZmqEndpoint('connect', config.get('sub-endpoint', DEFAULT_SUB_ENDPOINT)) self.zmq_pub = ZmqPubConnection(zmq_factory, sub_endpoint) def load_plugins(self): plugin_classes = list(getPlugins(IAutomatronPluginFactory)) for plugin_class in plugin_classes: try: zope.interface.verify.verifyObject(IAutomatronPluginFactory, plugin_class) except (zope.interface.verify.BrokenImplementation, zope.interface.verify.BrokenMethodImplementation) as e: log.err(e, 'Plugin %s is broken' % plugin_class.__name__) continue self.register_event_handler(plugin_class(self.controller)) def emit(self, event, *args): tag = '%s.%s' % (event.interface.getName(), event.getName()) self.zmq_pub.publish(cPickle.dumps(args), tag) def emit_internal(self, event, *args): tag = '%s.%s' % (event.interface.getName(), event.getName()) self.dispatch_event(tag, *args)
class PubModel(): ''' zmq 发布者模型 ''' def __init__(self, endpoint): if endpoint: logger.debug("开始运行 PUB 服务器,服务地址为:{}...".format(endpoint)) self._pub = ZmqPubConnection(ZmqFactory(), ZmqEndpoint("bind", endpoint)) def publishData(self, tag, data): ''' 从push服务器向外推送数据 :param tag: :param data: :return: ''' self._pub.publish(data, tag) def publish(self, tag, data): ''' 从push服务器向外推送数据 :param tag: :param data: :return: ''' self._pub.publish(data, tag)
class Client(): def __init__(self, identity): self.identity = identity # read the publish from the configuration file publish_port, self.pub_key = self.__read_conf() print("I am at the publish port:") print(publish_port) # create a factory self.factory = ZmqFactory() # create a connection to publish publish_endpoint = ZmqEndpoint(ZmqEndpointType.bind, "tcp://127.0.0.1:" + publish_port) self.publisher = ZmqPubConnection(self.factory, publish_endpoint) def broadcast(self, data): tag = "transaction" transaction = Transaction(data, self.pub_key) signed_data = self.sign(transaction.get_json()) #print("Client.py Signed_data") #print(signed_data) self.publisher.publish(signed_data, tag.encode()) def sign(self, data): filename = "../keys/clients/client" + str(self.identity) + ".key" key = RSA.importKey(open(filename).read()) h = SHA256.new(data.encode()) signature = pkcs1_15.new(key).sign(h) message = {} message['content'] = data message['signature'] = list(signature) # integer array return json.dumps(message).encode() #def sign(self, data): #filename = "../keys/clients/client"+str(self.identity)+".key" #key = RSA.importKey(open(filename).read()) #h = SHA256.new(data.encode()) #signature = pkcs1_15.new(key).sign(h) #return data.encode() + b"signature:" + signature # We assume the config file is well formed # Read the port corresponding to its id from the configuration port def __read_conf(self): publish_port = None file = open('../conf/miner_discovery.json') data = json.load(file) for client in data['clients']: port = client['port'] if client['id'] == self.identity: publish_port = port pub_key = RSA.import_key(client['pub_key']) break if publish_port is None: raise Exception("No publish port for miner with id: " + str(self.identity)) return publish_port, pub_key
class Leds: def __init__(self): factory = ZmqFactory() pub_endpoint = ZmqEndpoint(ZmqEndpointType.bind, PUBLISH_ENDPOINT) self.pub_connection = ZmqPubConnection(factory, pub_endpoint) self.current_idle = "OCD" def set_mode(self, mode): assert mode in MODES, "unknown mode" msg = mode.encode("utf8") self.pub_connection.publish(msg, tag=TAG) def new_idle_mode(self): while True: new = random.choice(tuple(IDLE_MODES)) if new != self.current_idle: self.current_idle = new return new
class Broadcast: def __init__(self, miner): # create a factory self.miner = miner self.factory = ZmqFactory() # create a connection to publish publish_endpoint = ZmqEndpoint(ZmqEndpointType.bind, "tcp://127.0.0.1:" + miner.publish_port) self.publisher = ZmqPubConnection(self.factory, publish_endpoint) # create connections to subscribe self.subscribers = [] print("the ports subscribed are:") print(miner.subscribe_ports) for subscribe_port in miner.subscribe_ports: subscribe_endpoint = ZmqEndpoint( ZmqEndpointType.connect, "tcp://127.0.0.1:" + subscribe_port) subscriber = BroadcastSubscriber(self.factory, subscribe_endpoint, miner) self.subscribers.append(subscriber) # subscribe to the types of events subscriber.subscribe(PROPOSAL_TAG.encode()) subscriber.subscribe(COMMIT_TAG.encode()) subscriber.subscribe(REINFORCEMENT_TAG.encode()) subscriber.subscribe(TRANSACTION_TAG.encode()) subscriber.subscribe(MALICIOUS_PROPOSAL_AGREEMENT_TAG.encode()) subscriber.subscribe(PROPOSAL_COMMIT_TAG.encode()) subscriber.subscribe(REINFORCEMENT_INF_TAG.encode()) def broadcast(self, data, tag): logging.info("SNT %s", tag) signed_data = self.sign(data) #print("Broadcast.py Signed Data:") #print(signed_data) self.publisher.publish(signed_data, tag.encode()) def sign(self, data): filename = "../keys/miners/miner" + str(self.miner.id) + ".key" key = RSA.importKey(open(filename).read()) h = SHA256.new(data.encode()) signature = pkcs1_15.new(key).sign(h) message = {} message['content'] = data message['signature'] = list(signature) # integer array return json.dumps(message).encode()
class ZeHub(object): """ Actual business logic of this example: Hub opens a central server publisher socket and then on demand builds client sockets """ def __init__(self): self.zf = ZmqFactory() self.bind_to = "tcp://127.0.0.1:5555" #These are just a namedtuples that hold the connection type AND # the target address. self.server = ZmqEndpoint('bind', self.bind_to) self.client = ZmqEndpoint('connect', self.bind_to) #The actual publisher/server socket self.server_s = ZmqPubConnection(self.zf, self.server) #A brute force way to hold client sockets and prevent them from # getting lost. self.clients = [] def send(self, msg): """ Publishes a message onto the pub/sub :param msg: Expected to be a simple string message """ self.server_s.publish(msg) def on_msg(self, callBack, time_out = None): """ A messy callback handler for when a new message pops up. :param callBack: expected def callBack(stringMessage) :param time_out: TODO a timeout value in seconds """ """ This is a tad not production sane as its going to open a new ZMQ socket for every single message sent. Its fine when it's just 1-2 people chatting for a short-demo duration but a better approach might be to bind the client ZMQ socket to a HTTP session with a timeout. So say someone leaves, the HTTP session would timeout after some T duration and this socket would be cleaned up. Additionally this would prevent some amount of thrash of instantiating and destroying sockets. """ client = ZmqSubConnection(self.zf, self.client) client.subscribe("") self.clients.append(client) print len(self.clients), " waiting clients" def cleanup(): """ Our message is done, clean up! """ c_index = self.clients.index(client) self.clients.pop(c_index) client.shutdown() def on_msg(*args, **kwargs): try: callBack("".join(args[:-1])) finally: cleanup() """ Blink and you might miss it, this does the actual binding to the client socket. Initially I thought "Man this would be some much better using a deferred" EXCEPT what happens after that first deferred fires? """ client.gotMessage = on_msg