def __init__(self, hub, config): self.config = config self.validate_config(self.config) self.strict = asbool(self.config.get('zmq_strict', False)) self.subscriber_factories = {} self.context = zmq.Context(1) # Configure txZMQ to use our highwatermark and keepalive if we have 'em self.connection_cls = txzmq.ZmqSubConnection self.connection_cls.highWaterMark = \ config.get('high_water_mark', 0) self.connection_cls.tcpKeepalive = \ config.get('zmq_tcp_keepalive', 0) self.connection_cls.tcpKeepaliveCount = \ config.get('zmq_tcp_keepalive_cnt', 0) self.connection_cls.tcpKeepaliveIdle = \ config.get('zmq_tcp_keepalive_idle', 0) self.connection_cls.tcpKeepaliveInterval = \ config.get('zmq_tcp_keepalive_intvl', 0) # Set up the publishing socket self.pub_socket = self.context.socket(zmq.PUB) _endpoints = self.config.get('zmq_publish_endpoints', '').split(',') for endpoint in (e for e in _endpoints if e): log.info("Binding publish socket to '%s'" % endpoint) try: self.pub_socket.bind(endpoint) except zmq.ZMQError: map(self.pub_socket.bind, hostname2ipaddr(endpoint)) # Factory used to lazily produce subsequent subscribers self.twisted_zmq_factory = txzmq.ZmqFactory() # Establish a list of subscription endpoints for later use _endpoints = self.config['zmq_subscribe_endpoints'].split(',') method = self.config.get('zmq_subscribe_method', 'connect') if method == 'bind': _endpoints = sum(map(list, map(hostname2ipaddr, _endpoints)), []) else: # Required for zeromq-3.x. _endpoints = sum(map(list, map(splat2ipaddr, _endpoints)), []) self.sub_endpoints = [ txzmq.ZmqEndpoint(method, ep) for ep in _endpoints ] # This is required so that the publishing socket can fully set itself # up before we start trying to send messages on it. This is a # documented zmq issue that they do not plan to fix. time.sleep(1) super(ZMQHubExtension, self).__init__()
def dataReceived(self, data): """ Messages sent from the browser arrive here. This hook: 1) Acts on any special control messages 2) Forwards messages onto the zeromq hub """ try: json = JSON.loads(data) if json['topic'] == '__topic_subscribe__': # If this is a custom control message, then subscribe. def send_to_websocket(zmq_message): """ Callback. Sends a message to the browser """ msg = JSON.dumps({ 'topic': zmq_message.topic, 'body': JSON.loads(zmq_message.body), }) self.transport.write(msg) # TODO -- the following "subscribed-already" logic can # be thrown away. It is a stand-in until we can decide # on a more solid websocket authn/authz+routing # architecture like blastbeat, socketio, or autobahn. _topic = json['body'] if not self.subscribed_already: self.subscribed_already = True _topic = "*" log.info("Websocket subscribing to %r." % _topic) self.moksha_hub.subscribe(_topic, send_to_websocket) else: log.debug("Websocket ignoring %r." % _topic) else: # FIXME - The following is disabled temporarily until we can # devise a secure method of "firewalling" where messages # can and can't go. See the following for more info: # https://fedorahosted.org/moksha/ticket/245 # https://github.com/gregjurman/zmqfirewall key = 'moksha.livesocket.websocket.client2server' if asbool(self.moksha_hub.config.get(key, False)): # Simply forward on the message through the hub. self.moksha_hub.send_message( json['topic'], json['body'], ) except Exception as e: import traceback log.error(traceback.format_exc())
def __init__(self, hub, config): import amqplib.client_0_8 as amqp self.config = config broker = self.config.get('amqp_broker') ssl = asbool(self.config.get('amqp_broker_ssl', False)) use_threading = asbool(self.config.get('amqp_broker_threaded', False)) username = self.config.get('amqp_broker_username', 'guest') password = self.config.get('amqp_broker_password', 'guest') self.conn = amqp.Connection(host=broker, ssl=ssl, use_threading=use_threading, userid=username, password=password) self.channel = self.conn.channel() self.channel.access_request('/data', active=True, write=True, read=True) super(AMQPLibHubExtension, self).__init__()
def __init__(self, hub, config): import amqplib.client_0_8 as amqp self.config = config broker = self.config.get('amqp_broker') ssl = asbool(self.config.get('amqp_broker_ssl', False)) use_threading = asbool(self.config.get('amqp_broker_threaded', False)) username = self.config.get('amqp_broker_username', 'guest') password = self.config.get('amqp_broker_password', 'guest') self.conn = amqp.Connection( host=broker, ssl=ssl, use_threading=use_threading, userid=username, password=password ) self.channel = self.conn.channel() self.channel.access_request( '/data', active=True, write=True, read=True) super(AMQPLibHubExtension, self).__init__()
def dataReceived(self, data): """ Messages sent from the browser arrive here. This hook: 1) Acts on any special control messages 2) Forwards messages onto the zeromq hub """ try: json = JSON.loads(data) if json['topic'] == '__topic_subscribe__': # If this is a custom control message, then subscribe. def send_to_websocket(zmq_message): """ Callback. Sends a message to the browser """ msg = JSON.dumps({ 'topic': zmq_message.topic, 'body': JSON.loads(zmq_message.body), }) self.transport.write(msg) _topic = json['body'] log.info("Websocket subscribing to %r." % _topic) self.moksha_hub.subscribe( _topic, send_to_websocket, ) else: # FIXME - The following is disabled temporarily until # we can devise a secure method of "firewalling" where # messages can and can't go. See the following for # more info: # https://fedorahosted.org/moksha/ticket/245 # https://github.com/gregjurman/zmqfirewall key = 'moksha.livesocket.websocket.client2server' if asbool(self.moksha_hub.config.get(key, False)): # Simply forward on the message through the hub. self.moksha_hub.send_message( json['topic'], json['body'], ) except Exception as e: import traceback log.error(traceback.format_exc())
def validate_config(self, config): if not asbool(config.get('zmq_enabled', False)): raise ValueError("zmq_enabled not set to True") required_attrs = ['zmq_publish_endpoints', 'zmq_subscribe_endpoints'] for attr in required_attrs: if not config.get(attr, None): log.warn("No '%s' set. Are you sure?" % attr) continue endpoints = config[attr].split(',') for endpoint in endpoints: if 'localhost' in endpoint: # This is why http://bit.ly/Jwdf6v raise ValueError("'localhost' in %s is disallowed" % attr)
def __init__(self, hub, config): self.config = config self.validate_config(self.config) self.strict = asbool(self.config.get("zmq_strict", False)) self.subscriber_factories = {} self.context = zmq.Context(1) # Set up the publishing socket self.pub_socket = self.context.socket(zmq.PUB) _endpoints = self.config.get("zmq_publish_endpoints", "").split(",") for endpoint in (e for e in _endpoints if e): log.info("Binding publish socket to '%s'" % endpoint) try: self.pub_socket.bind(endpoint) except zmq.ZMQError: map(self.pub_socket.bind, hostname2ipaddr(endpoint)) # Factory used to lazily produce subsequent subscribers self.twisted_zmq_factory = txzmq.ZmqFactory() # Establish a list of subscription endpoints for later use _endpoints = self.config["zmq_subscribe_endpoints"].split(",") method = self.config.get("zmq_subscribe_method", "connect") if method == "bind": _endpoints = sum(map(list, map(hostname2ipaddr, _endpoints)), []) else: # Required for zeromq-3.x. _endpoints = sum(map(list, map(splat2ipaddr, _endpoints)), []) self.sub_endpoints = [txzmq.ZmqEndpoint(method, ep) for ep in _endpoints] # This is required so that the publishing socket can fully set itself # up before we start trying to send messages on it. This is a # documented zmq issue that they do not plan to fix. time.sleep(1) super(ZMQHubExtension, self).__init__()