def setup(self): """Create a simple SASL configuration. This assumes saslpasswd2 is in the OS path, otherwise the test will be skipped. """ super(CyrusTest, self).setup() if not CyrusTest.CONF_DIR: raise common.Skipped("Cyrus SASL not supported") self.container1 = pyngus.Container("test-container-1") self.container2 = pyngus.Container("test-container-2")
def __init__(self, server_prefix="exclusive", broadcast_prefix="broadcast", group_prefix="unicast", address_separator=".", sock_addr="", sock_port=0, sasl_mechanisms="ANONYMOUS", user_credentials=None): """Create a fake broker listening on sock_addr:sock_port.""" if not pyngus: raise AssertionError("pyngus module not present") threading.Thread.__init__(self) self._server_prefix = server_prefix + address_separator self._broadcast_prefix = broadcast_prefix + address_separator self._group_prefix = group_prefix + address_separator self._address_separator = address_separator self._sasl_mechanisms = sasl_mechanisms self._user_credentials = user_credentials self._wakeup_pipe = os.pipe() self._my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._my_socket.bind((sock_addr, sock_port)) self.host, self.port = self._my_socket.getsockname() self.container = pyngus.Container("test_server_%s:%d" % (self.host, self.port)) self._connections = {} self._sources = {} # count of messages forwarded, by messaging pattern self.direct_count = 0 self.topic_count = 0 self.fanout_count = 0 self.dropped_count = 0
def test_create_destroy(self): gc.enable() gc.collect() assert not gc.garbage, "Object leak: %s" % str(gc.garbage) container = pyngus.Container("My-Container") assert container.name == "My-Container" container.destroy()
def test_need_processing(self): gc.enable() gc.collect() assert not gc.garbage, "Object leak: %s" % str(gc.garbage) container = pyngus.Container("abc") c1 = container.create_connection("c1") c2 = container.create_connection("c2") props = {"idle-time-out": 10} c3 = container.create_connection("c3", properties=props) c4 = container.create_connection("c4") c1.open() c2.open() c3.open() c4.open() # every connection should need both input and output, # but no timers yet (connection's not up) r, w, t = container.need_processing() assert c1 in r and c1 in w assert c2 in r and c2 in w assert c3 in r and c3 in w assert c4 in r and c4 in w assert not t common.process_connections(c1, c2) common.process_connections(c3, c4) # After connections come up, no connection should need to do I/O, and # only c4 and c4 should be in the timer list: r, w, t = container.need_processing() assert c1 in r assert c2 in r assert c3 in r assert c4 in r assert not w assert len(t) == 2 and c3 in t and c4 in t container.destroy()
def setup(self, conn1_props=None, conn2_props=None): super(APITest, self).setup() # logging.getLogger("pyngus").setLevel(logging.DEBUG) self.container1 = pyngus.Container("test-container-1") self.conn1_handler = common.ConnCallback() if conn1_props is None: # props = {"x-trace-protocol": True} conn1_props = {"x-trace-protocol": False} self.conn1 = self.container1.create_connection("conn1", self.conn1_handler, conn1_props) self.conn1.open() self.container2 = pyngus.Container("test-container-2") self.conn2_handler = common.ConnCallback() self.conn2 = self.container2.create_connection("conn2", self.conn2_handler, conn2_props) self.conn2.open()
def test_create_connection(self): gc.enable() gc.collect() assert not gc.garbage, "Object leak: %s" % str(gc.garbage) container = pyngus.Container("A123") container.create_connection("c1") container.create_connection("c2") c1 = container.get_connection("c1") assert c1 and c1.name == "c1", "Connection not found!" c3 = container.get_connection("c3") assert not c3, "Bad connection returned!" container.destroy() del c1
def __init__(self, container_name=None): super(Thread, self).__init__() # callables from other threads: self._requests = Requests() # delayed callables (only used on this thread for now): self._schedule = Schedule() # Configure a container if container_name is None: container_name = "Container-" + uuid.uuid4().hex self._container = pyngus.Container(container_name) self.name = "Thread for Proton container: %s" % self._container.name self._shutdown = False self.daemon = True self.start()
def __init__(self, container_name, node, command, pid): super(Thread, self).__init__() # callables from other threads: self._requests = Requests() # delayed callables (only used on this thread for now): self._scheduler = Scheduler() # Configure a container if container_name is None: container_name = ("openstack.org/om/container/%s/%s/%s/%s" % (node, command, pid, uuid.uuid4().hex)) self._container = pyngus.Container(container_name) self.name = "Thread for Proton container: %s" % self._container.name self._shutdown = False self.daemon = True self.start()
def test_cleanup(self): gc.enable() gc.collect() assert not gc.garbage, "Object leak: %s" % str(gc.garbage) container = pyngus.Container("abc") c1 = container.create_connection("c1") c2 = container.create_connection("c2") assert c2 del c2 gc.collect() c2 = container.get_connection("c2") assert c2 c1 = container.get_connection("c1") assert c1 c1.create_receiver("r1") c1.create_sender("s1") del c1 del c2 container.destroy() del container gc.collect() assert not gc.garbage, "Object leak: %s" % str(gc.garbage)
def setup(self): super(APITest, self).setup() # logging.getLogger("pyngus").setLevel(logging.DEBUG) self.container1 = pyngus.Container("test-container-1") self.container2 = pyngus.Container("test-container-2")
def main(argv=None): _usage = """Usage: %prog [options]""" parser = optparse.OptionParser(usage=_usage) parser.add_option("-a", dest="server", type="string", default="amqp://0.0.0.0:5672", help="The address of the server [amqp://0.0.0.0:5672]") parser.add_option("--node", type='string', default='amq.topic', help='Name of source/target node') parser.add_option("--count", type='int', default=100, help='Send N messages (send forever if N==0)') parser.add_option("--debug", dest="debug", action="store_true", help="enable debug logging") parser.add_option("--trace", dest="trace", action="store_true", help="enable protocol tracing") opts, _ = parser.parse_args(args=argv) if opts.debug: LOG.setLevel(logging.DEBUG) host, port = get_host_port(opts.server) my_socket = connect_socket(host, port) # create AMQP Container, Connection, and SenderLink # container = pyngus.Container(uuid.uuid4().hex) conn_properties = {'hostname': host, 'x-server': False} if opts.trace: conn_properties["x-trace-protocol"] = True c_handler = ConnectionEventHandler() connection = container.create_connection("perf_tool", c_handler, conn_properties) r_handler = ReceiverHandler(opts.count, opts.count or 1000) receiver = connection.create_receiver(opts.node, opts.node, r_handler) s_handler = SenderHandler(opts.count) sender = connection.create_sender(opts.node, opts.node, s_handler) connection.open() receiver.open() while not receiver.active: process_connection(connection, my_socket) sender.open() # Run until all messages transfered while not sender.closed or not receiver.closed: process_connection(connection, my_socket) connection.close() while not connection.closed: process_connection(connection, my_socket) duration = s_handler.stop_time - s_handler.start_time thru = s_handler.calls / duration permsg = duration / s_handler.calls ack = s_handler.total_ack_latency / s_handler.calls lat = r_handler.tx_total_latency / r_handler.receives print("Stats:\n" " TX Avg Calls/Sec: %f Per Call: %f Ack Latency %f\n" " RX Latency: %f" % (thru, permsg, ack, lat)) sender.destroy() receiver.destroy() connection.destroy() container.destroy() my_socket.close() return 0
def main(argv=None): _usage = """Usage: %prog [options] method arg1 value1 [arg2 value2] ...""" parser = optparse.OptionParser(usage=_usage) parser.add_option("-a", dest="server", type="string", default="amqp://0.0.0.0:5672", help="The address of the server [amqp://0.0.0.0:5672]") parser.add_option("-t", "--timeout", dest="timeout", type="int", help="timeout used when waiting for reply, in seconds") parser.add_option("--repeat", dest="repeat", type="int", default=1, help="Repeat the RPC call REPEAT times (0 == forever)") parser.add_option("--trace", dest="trace", action="store_true", help="enable protocol tracing") parser.add_option("--debug", dest="debug", action="store_true", help="enable debug logging") parser.add_option("--ca", help="Certificate Authority PEM file") opts, method_info = parser.parse_args(args=argv) if not method_info: assert False, "No method info specified!" if len(method_info) % 2 != 1: assert False, "An even number of method arguments are required!" if opts.debug: LOG.setLevel(logging.DEBUG) # Create a socket connection to the server # regex = re.compile(r"^amqp://([a-zA-Z0-9.]+)(:([\d]+))?$") LOG.debug("Connecting to %s", opts.server) x = regex.match(opts.server) if not x: raise Exception("Bad address syntax: %s" % opts.server) matches = x.groups() host = matches[0] port = int(matches[2]) if matches[2] else None addr = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM) if not addr: raise Exception("Could not translate address '%s'" % opts.server) my_socket = socket.socket(addr[0][0], addr[0][1], addr[0][2]) my_socket.setblocking(0) # 0=non-blocking try: my_socket.connect(addr[0][4]) except socket.error as e: if e.errno != errno.EINPROGRESS: raise # create AMQP container, connection, sender and receiver # container = pyngus.Container(uuid.uuid4().hex) conn_properties = {} if opts.trace: conn_properties["x-trace-protocol"] = True if opts.ca: conn_properties["x-ssl-ca-file"] = opts.ca my_connection = MyConnection("to-server", container, conn_properties) # Create the RPC caller method = { 'method': method_info[0], 'args': dict([(method_info[i], method_info[i + 1]) for i in range(1, len(method_info), 2)]) } my_caller = my_connection.create_caller(method, "my-source-address", "my-target-address", receiver_properties={}, sender_properties={}) try: my_connection.connect(my_socket) repeat = 0 while opts.repeat == 0 or repeat < opts.repeat: LOG.debug("Requesting RPC...") my_caller.connect() while not my_caller.done(): my_connection.process() LOG.debug("RPC completed! Closing caller...") my_caller.close() while not my_caller.closed(): my_connection.process() LOG.debug("Caller closed cleanly!") repeat += 1 print("Closing connections") my_connection.close() while not my_connection.closed: my_connection.process() LOG.debug("Connection closed") my_caller.destroy() my_connection.destroy() except Exception as e: LOG.error("Unexpected exception occured: %s", str(e)) return -1 return 0
def main(argv=None): _usage = """Usage: %prog [options] [message content string]""" parser = optparse.OptionParser(usage=_usage) parser.add_option("-a", dest="server", type="string", default="amqp://0.0.0.0:5672", help="The address of the server [amqp://0.0.0.0:5672]") parser.add_option("--idle", dest="idle_timeout", type="int", default=0, help="Idle timeout for connection (seconds).") parser.add_option("--debug", dest="debug", action="store_true", help="enable debug logging") parser.add_option("--source", dest="source_addr", type="string", help="Address for link source.") parser.add_option("--target", dest="target_addr", type="string", help="Address for link target.") parser.add_option("--trace", dest="trace", action="store_true", help="enable protocol tracing") parser.add_option("-f", "--forever", action="store_true", help="Keep sending forever") parser.add_option("--ca", help="Certificate Authority PEM file") parser.add_option("--ssl-cert-file", help="Self-identifying certificate (PEM file)") parser.add_option("--ssl-key-file", help="Key for self-identifying certificate (PEM file)") parser.add_option("--ssl-key-password", help="Password to unlock SSL key file") parser.add_option("--username", type="string", help="User Id for authentication") parser.add_option("--password", type="string", help="User password for authentication") parser.add_option("--sasl-mechs", type="string", help="The list of acceptable SASL mechs") parser.add_option("--sasl-config-dir", type="string", help="Path to directory containing sasl config") parser.add_option("--sasl-config-name", type="string", help="Name of the sasl config file (without '.config')") opts, payload = parser.parse_args(args=argv) if not payload: payload = "Hi There!" if opts.debug: LOG.setLevel(logging.DEBUG) host, port = get_host_port(opts.server) my_socket = connect_socket(host, port) # create AMQP Container, Connection, and SenderLink # container = pyngus.Container(uuid.uuid4().hex) conn_properties = {'hostname': host, 'x-server': False} if opts.trace: conn_properties["x-trace-protocol"] = True if opts.ca: conn_properties["x-ssl-ca-file"] = opts.ca if opts.ssl_cert_file: conn_properties["x-ssl-identity"] = (opts.ssl_cert_file, opts.ssl_key_file, opts.ssl_key_password) if opts.idle_timeout: conn_properties["idle-time-out"] = opts.idle_timeout if opts.username: conn_properties['x-username'] = opts.username if opts.password: conn_properties['x-password'] = opts.password if opts.sasl_mechs: conn_properties['x-sasl-mechs'] = opts.sasl_mechs if opts.sasl_config_dir: conn_properties["x-sasl-config-dir"] = opts.sasl_config_dir if opts.sasl_config_name: conn_properties["x-sasl-config-name"] = opts.sasl_config_name c_handler = ConnectionEventHandler() connection = container.create_connection("sender", c_handler, conn_properties) connection.open() source_address = opts.source_addr or uuid.uuid4().hex s_handler = SenderEventHandler() sender = connection.create_sender(source_address, opts.target_addr, s_handler) sender.open() class SendCallback(object): def __init__(self): self.done = False self.status = None def __call__(self, link, handle, status, error): self.done = True self.status = status while True: # Send a single message: msg = Message() msg.body = str(payload) cb = SendCallback() sender.send(msg, cb) # Poll connection until SendCallback is invoked: while not cb.done: process_connection(connection, my_socket) if c_handler.error: break if connection.closed: break if cb.done: print("Send done, status=%s" % SEND_STATUS.get(cb.status, "???")) else: print("Send failed due to connection failure: %s" % c_handler.error or "remote closed unexpectedly") break if not opts.forever: break if not sender.closed: sender.close() if not connection.closed: connection.close() # Poll connection until close completes: while not c_handler.error and not connection.closed: process_connection(connection, my_socket) sender.destroy() connection.destroy() container.destroy() my_socket.close() return 0
def main(argv=None): _usage = """Usage: %prog [options]""" parser = optparse.OptionParser(usage=_usage) parser.add_option("--count", dest="count", type="int", default=10000, help="# of messages to transfer per link.") parser.add_option("--links", dest="link_count", type="int", default=20, help="# of link pairs.") parser.add_option("--send-batch", dest="send_batch", type="int", default=10, help="DEPRECATED") parser.add_option("--credit", dest="credit_window", type="int", default=10, help="Credit window issued by receiver.") parser.add_option("--ca", help="Certificate Authority PEM file") parser.add_option("--cert", help="PEM File containing the server's certificate") parser.add_option("--key", help="PEM File containing the server's private key") parser.add_option("--keypass", help="Password used to decrypt key file") opts, extra = parser.parse_args(args=argv) container = pyngus.Container(uuid.uuid4().hex) # sender acts like SSL client conn_properties = { 'hostname': "test.server.com", 'x-trace-protocol': False, 'x-sasl-mechs': "ANONYMOUS" } if opts.ca: conn_properties["x-ssl-ca-file"] = opts.ca sender_conn = PerfSendConnection("send-conn", container, conn_properties, opts.count, opts.link_count) # receiver acts as SSL server conn_properties = { 'hostname': "my.client.com", 'x-server': True, 'x-sasl-mechs': "ANONYMOUS" } if opts.cert: identity = (opts.cert, opts.key, opts.keypass) conn_properties["x-ssl-identity"] = identity receiver_conn = PerfReceiveConnection("recv-conn", container, conn_properties, opts.count, opts.credit_window) # process connections until finished: start = time.time() while ((not sender_conn.connection.closed) or (not receiver_conn.connection.closed)): process_connections(sender_conn.connection, receiver_conn.connection) sender_conn.connection.destroy() receiver_conn.connection.destroy() container.destroy() delta = time.time() - start total = opts.count * opts.link_count print("Total: %s messages; credit window: %s; proton %s" % (total, opts.credit_window, PN_VERSION)) print( "%d Messages/second; Latency avg: %.3fms min: %.3fms max: %.3fms" % (total / delta, (receiver_conn.latency / total) * 1000.0, receiver_conn.latency_min * 1000.0, receiver_conn.latency_max * 1000.0)) return 0
def __init__(self, server, ca, ssl_cert_file, ssl_key_file, ssl_key_password, source): # opts, extra = parser.parse_args(args=argv) # if opts.debug: # LOG.setLevel(logging.DEBUG) #self.server = server host, port = get_host_port(server) my_socket = connect_socket(host, port, blocking=False) # create AMQP Container, Connection, and SenderLink # container = pyngus.Container(uuid.uuid4().hex) conn_properties = {'hostname': host, 'x-server': False} conn_properties["x-trace-protocol"] = True conn_properties["x-ssl-ca-file"] = ca conn_properties["x-ssl-identity"] = (ssl_cert_file, ssl_key_file, ssl_key_password) # if opts.idle_timeout: # conn_properties["idle-time-out"] = opts.idle_timeout # if opts.username: # conn_properties['x-username'] = opts.username # if opts.password: # conn_properties['x-password'] = opts.password # if opts.sasl_mechs: # conn_properties['x-sasl-mechs'] = opts.sasl_mechs # if opts.sasl_config_dir: # conn_properties["x-sasl-config-dir"] = opts.sasl_config_dir # if opts.sasl_config_name: # conn_properties["x-sasl-config-name"] = opts.sasl_config_name #conn_properties["x-force-sasl"] = True with open(ca, "r") as f: print("reading first line from certificate to ensure we have it") print(f.readline()) conn_properties["x-ssl-verify-mode"] = "no-verify" c_handler = ConnectionEventHandler() connection = container.create_connection("receiver", c_handler, conn_properties) connection.open() target_address = uuid.uuid4().hex cb = ReceiverEventHandler() receiver = connection.create_receiver(target_address, source, cb) receiver.add_capacity(1) receiver.open() # Poll connection until something arrives while not cb.done and not connection.closed: process_connection(connection, my_socket) if cb.done: print("Receive done, message=%s" % str(cb.message) if cb. message else "ERROR: no message received") if cb.handle: receiver.message_accepted(cb.handle) else: print("Receive failed due to connection failure!") # flush any remaining output before closing (optional) while connection.has_output > 0: process_connection(connection, my_socket) receiver.close() connection.close() # Poll connection until close completes: while not connection.closed: process_connection(connection, my_socket) receiver.destroy() connection.destroy() container.destroy() my_socket.close()
def main(argv=None): _usage = """Usage: %prog [options]""" parser = optparse.OptionParser(usage=_usage) parser.add_option("-a", dest="server", type="string", default="amqp://0.0.0.0:5672", help="The address of the server [amqp://0.0.0.0:5672]") parser.add_option("--idle", dest="idle_timeout", type="int", default=0, help="Idle timeout for connection (seconds).") parser.add_option("--debug", dest="debug", action="store_true", help="enable debug logging") parser.add_option("--source", dest="source_addr", type="string", help="Address for link source.") parser.add_option("--target", dest="target_addr", type="string", help="Address for link target.") parser.add_option("--trace", dest="trace", action="store_true", help="enable protocol tracing") parser.add_option("-f","--forever", action="store_true", help="don't stop receiving") parser.add_option("--ca", help="Certificate Authority PEM file") parser.add_option("--ssl-cert-file", help="Self-identifying certificate (PEM file)") parser.add_option("--ssl-key-file", help="Key for self-identifying certificate (PEM file)") parser.add_option("--ssl-key-password", help="Password to unlock SSL key file") parser.add_option("--username", type="string", help="User Id for authentication") parser.add_option("--password", type="string", help="User password for authentication") parser.add_option("--sasl-mechs", type="string", help="The list of acceptable SASL mechs") parser.add_option("--sasl-config-dir", type="string", help="Path to directory containing sasl config") parser.add_option("--sasl-config-name", type="string", help="Name of the sasl config file (without '.config')") opts, extra = parser.parse_args(args=argv) if opts.debug: LOG.setLevel(logging.DEBUG) host, port = get_host_port(opts.server) my_socket = connect_socket(host, port) # create AMQP Container, Connection, and SenderLink # container = pyngus.Container(uuid.uuid4().hex) conn_properties = {'hostname': host, 'x-server': False} if opts.trace: conn_properties["x-trace-protocol"] = True if opts.ca: conn_properties["x-ssl-ca-file"] = opts.ca if opts.ssl_cert_file: conn_properties["x-ssl-identity"] = (opts.ssl_cert_file, opts.ssl_key_file, opts.ssl_key_password) if opts.idle_timeout: conn_properties["idle-time-out"] = opts.idle_timeout if opts.username: conn_properties['x-username'] = opts.username if opts.password: conn_properties['x-password'] = opts.password if opts.sasl_mechs: conn_properties['x-sasl-mechs'] = opts.sasl_mechs if opts.sasl_config_dir: conn_properties["x-sasl-config-dir"] = opts.sasl_config_dir if opts.sasl_config_name: conn_properties["x-sasl-config-name"] = opts.sasl_config_name c_handler = ConnectionEventHandler() connection = container.create_connection("receiver", c_handler, conn_properties) connection.open() target_address = opts.target_addr or uuid.uuid4().hex cb = ReceiverEventHandler() receiver = connection.create_receiver(target_address, opts.source_addr, cb) receiver.add_capacity(1) receiver.open() while True: # Poll connection until something arrives while not cb.done: process_connection(connection, my_socket) if c_handler.error: break if connection.closed: break if cb.done: print("Receive done, message=%s" % str(cb.message) if cb.message else "ERROR: no message received") if cb.handle: receiver.message_accepted(cb.handle) else: print("Receive failed due to connection failure: %s" % c_handler.error or "remote closed unexpectedly") break if not opts.forever: break cb.done = False receiver.add_capacity(1) # Poll connection until close completes: while not c_handler.error and not connection.closed: process_connection(connection, my_socket) receiver.destroy() connection.destroy() container.destroy() my_socket.close() return 0
def main(argv=None): _usage = """Usage: %prog [options]""" parser = optparse.OptionParser(usage=_usage) parser.add_option("-a", dest="address", type="string", default="amqp://0.0.0.0:5672", help="Server address [amqp://0.0.0.0:5672]") parser.add_option("--idle", dest="idle_timeout", type="float", default=30, help="timeout for an idle link, in seconds") parser.add_option("--trace", dest="trace", action="store_true", help="enable protocol tracing") parser.add_option("--debug", dest="debug", action="store_true", help="enable debug logging") parser.add_option("--ssl-cert-file", help="PEM File containing the server's certificate") parser.add_option("--ssl-key-file", help="PEM File containing the server's private key") parser.add_option("--ssl-key-password", help="Password used to decrypt key file") parser.add_option("--ca", help="Certificate Authority PEM file") parser.add_option("--require-auth", action="store_true", help="Require clients to authenticate") parser.add_option("--sasl-mechs", type="string", help="The list of acceptable SASL mechs") parser.add_option("--sasl-cfg-name", type="string", help="name of SASL config file (no suffix)") parser.add_option("--sasl-cfg-dir", type="string", help="Path to the SASL config file") opts, arguments = parser.parse_args(args=argv) if opts.debug: LOG.setLevel(logging.DEBUG) # Create a socket for inbound connections # host, port = get_host_port(opts.address) my_socket = server_socket(host, port) # create an AMQP container that will 'provide' the Server service # container = pyngus.Container("Server") socket_connections = set() # Main loop: process I/O and timer events: # while True: readers, writers, timers = container.need_processing() # map pyngus Connections back to my SocketConnections: readfd = [c.user_context for c in readers] writefd = [c.user_context for c in writers] timeout = None if timers: deadline = timers[0].next_tick # [0] == next expiring timer now = time.time() timeout = 0 if deadline <= now else deadline - now LOG.debug("select() start (t=%s)", str(timeout)) readfd.append(my_socket) readable, writable, ignore = select.select(readfd, writefd, [], timeout) LOG.debug("select() returned") worked = set() for r in readable: if r is my_socket: # new inbound connection request received, # create a new SocketConnection for it: client_socket, client_address = my_socket.accept() # name = uuid.uuid4().hex name = str(client_address) conn_properties = {'x-server': True} if opts.require_auth: conn_properties['x-require-auth'] = True if opts.sasl_mechs: conn_properties['x-sasl-mechs'] = opts.sasl_mechs if opts.sasl_cfg_name: conn_properties['x-sasl-config-name'] = opts.sasl_cfg_name if opts.sasl_cfg_dir: conn_properties['x-sasl-config-dir'] = opts.sasl_cfg_dir if opts.idle_timeout: conn_properties["idle-time-out"] = opts.idle_timeout if opts.trace: conn_properties["x-trace-protocol"] = True if opts.ca: conn_properties["x-ssl-server"] = True conn_properties["x-ssl-ca-file"] = opts.ca conn_properties["x-ssl-verify-mode"] = "verify-cert" if opts.ssl_cert_file: conn_properties["x-ssl-server"] = True identity = (opts.ssl_cert_file, opts.ssl_key_file, opts.ssl_key_password) conn_properties["x-ssl-identity"] = identity sconn = SocketConnection(container, client_socket, name, conn_properties) socket_connections.add(sconn) LOG.debug("new connection created name=%s", name) else: assert isinstance(r, SocketConnection) r.process_input() worked.add(r) for t in timers: now = time.time() if t.next_tick > now: break t.process(now) sc = t.user_context assert isinstance(sc, SocketConnection) worked.add(sc) for w in writable: assert isinstance(w, SocketConnection) w.send_output() worked.add(w) closed = False while worked: sc = worked.pop() # nuke any completed connections: if sc.closed: socket_connections.discard(sc) sc.destroy() closed = True else: # can free any closed links now (optional): for link in sc.sender_links | sc.receiver_links: if link.closed: link.destroy() if closed: LOG.debug("%d active connections present", len(socket_connections)) return 0
def main(argv=None): _usage = """Usage: %prog [options]""" parser = optparse.OptionParser(usage=_usage) parser.add_option("-a", dest="address", type="string", default="amqp://0.0.0.0:5672", help="""The socket address this server will listen on [amqp://0.0.0.0:5672]""") parser.add_option("--idle", dest="idle_timeout", type="float", help="timeout for an idle link, in seconds") parser.add_option("--trace", dest="trace", action="store_true", help="enable protocol tracing") parser.add_option("--debug", dest="debug", action="store_true", help="enable debug logging") parser.add_option("--cert", help="PEM File containing the server's certificate") parser.add_option("--key", help="PEM File containing the server's private key") parser.add_option("--keypass", help="Password used to decrypt key file") opts, arguments = parser.parse_args(args=argv) if opts.debug: LOG.setLevel(logging.DEBUG) # Create a socket for inbound connections # regex = re.compile(r"^amqp://([a-zA-Z0-9.]+)(:([\d]+))?$") LOG.debug("Listening on %s", opts.address) x = regex.match(opts.address) if not x: raise Exception("Bad address syntax: %s" % opts.address) matches = x.groups() host = matches[0] port = int(matches[2]) if matches[2] else None addr = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM) if not addr: raise Exception("Could not translate address '%s'" % opts.address) my_socket = socket.socket(addr[0][0], addr[0][1], addr[0][2]) my_socket.setblocking(0) # 0=non-blocking try: my_socket.bind((host, port)) my_socket.listen(10) except socket.error as e: if e.errno != errno.EINPROGRESS: raise # create an AMQP container that will 'provide' the RPC service # container = pyngus.Container("example RPC service") global socket_connections global dead_links while True: # # Poll for I/O & timers # readfd = [my_socket] writefd = [] readers, writers, timers = container.need_processing() # map pyngus Connections back to my SocketConnections for c in readers: sc = c.user_context assert sc and isinstance(sc, SocketConnection) readfd.append(sc) for c in writers: sc = c.user_context assert sc and isinstance(sc, SocketConnection) writefd.append(sc) timeout = None if timers: deadline = timers[0].next_tick # 0 == next expiring timer now = time.time() timeout = 0 if deadline <= now else deadline - now LOG.debug("select() start (t=%s)", str(timeout)) readable, writable, ignore = select.select(readfd, writefd, [], timeout) LOG.debug("select() returned") worked = [] for r in readable: if r is my_socket: # new inbound connection request client_socket, client_address = my_socket.accept() name = uuid.uuid4().hex assert name not in socket_connections conn_properties = {'x-server': True} if opts.idle_timeout: conn_properties["idle-time-out"] = opts.idle_timeout if opts.trace: conn_properties["x-trace-protocol"] = True if opts.cert: conn_properties["x-ssl-server"] = True identity = (opts.cert, opts.key, opts.keypass) conn_properties["x-ssl-identity"] = identity socket_connections[name] = SocketConnection( name, client_socket, container, conn_properties) LOG.debug("new connection created name=%s", name) else: assert isinstance(r, SocketConnection) r.process_input() worked.append(r) for t in timers: now = time.time() if t.next_tick > now: break t.process(now) sc = t.user_context assert isinstance(sc, SocketConnection) worked.append(sc) for w in writable: assert isinstance(w, SocketConnection) w.send_output() worked.append(w) # first, free any closed links: while dead_links: dead_links.pop().destroy() # then nuke any completed connections: closed = False while worked: sc = worked.pop() if sc.done: if sc.name in socket_connections: del socket_connections[sc.name] sc.destroy() closed = True if closed: LOG.debug("%d active connections present", len(socket_connections)) return 0