PROTON-1733: [cpp] access actual listening port for listen on port 0 Added proton::listener::port() to provide access to the port. Updated tests to listen on port 0 as a safe, portable way to allocate ports.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/d6cef7b8 Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/d6cef7b8 Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/d6cef7b8 Branch: refs/heads/master Commit: d6cef7b8ca32c470cbae57e6f7a6b7e4c508a06d Parents: 59cedf3 Author: Alan Conway <[email protected]> Authored: Thu Jan 4 15:52:47 2018 -0500 Committer: Alan Conway <[email protected]> Committed: Thu Jan 4 16:07:22 2018 -0500 ---------------------------------------------------------------------- examples/cpp/broker.cpp | 5 +- examples/cpp/direct_recv.cpp | 2 +- examples/cpp/direct_send.cpp | 2 +- examples/cpp/example_test.py | 107 +++++-------- examples/cpp/flow_control.cpp | 14 +- examples/cpp/server_direct.cpp | 4 +- examples/cpp/simple_recv.cpp | 1 - examples/cpp/ssl.cpp | 16 +- examples/cpp/ssl_client_cert.cpp | 22 ++- .../bindings/cpp/include/proton/listener.hpp | 5 + proton-c/bindings/cpp/src/container_test.cpp | 21 +-- proton-c/bindings/cpp/src/listener.cpp | 10 ++ .../cpp/src/proactor_container_impl.cpp | 2 +- proton-c/bindings/cpp/src/test_port.hpp | 160 ------------------- tools/py/proctest.py | 21 --- 15 files changed, 100 insertions(+), 292 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/broker.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp index 6637719..f48fb37 100644 --- a/examples/cpp/broker.cpp +++ b/examples/cpp/broker.cpp @@ -389,7 +389,6 @@ class broker { container_("broker"), queues_(container_), listener_(queues_) { container_.listen(addr, listener_); - std::cout << "broker listening on " << addr << std::endl; } void run() { @@ -410,6 +409,10 @@ class broker { return proton::connection_options().handler(*(new connection_handler(queues_))); } + void on_open(proton::listener& l) OVERRIDE { + std::cout << "broker listening on " << l.port() << std::endl; + } + void on_error(proton::listener&, const std::string& s) OVERRIDE { std::cerr << "listen error: " << s << std::endl; throw std::runtime_error(s); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/direct_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/direct_recv.cpp b/examples/cpp/direct_recv.cpp index c98a4bf..43a018c 100644 --- a/examples/cpp/direct_recv.cpp +++ b/examples/cpp/direct_recv.cpp @@ -48,7 +48,7 @@ class direct_recv : public proton::messaging_handler { void on_container_start(proton::container &c) OVERRIDE { listener = c.listen(url); - std::cout << "direct_recv listening on " << url << std::endl; + std::cout << "listening on " << listener.port() << std::endl; } void on_message(proton::delivery &d, proton::message &msg) OVERRIDE { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/direct_send.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/direct_send.cpp b/examples/cpp/direct_send.cpp index 2a2b3e2..b8cf93f 100644 --- a/examples/cpp/direct_send.cpp +++ b/examples/cpp/direct_send.cpp @@ -49,7 +49,7 @@ class simple_send : public proton::messaging_handler { void on_container_start(proton::container &c) OVERRIDE { listener = c.listen(url); - std::cout << "direct_send listening on " << url << std::endl; + std::cout << "direct_send listening on " << listener.port() << std::endl; } void on_sendable(proton::sender &sender) OVERRIDE { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/example_test.py ---------------------------------------------------------------------- diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py index fa6143f..df26a38 100644 --- a/examples/cpp/example_test.py +++ b/examples/cpp/example_test.py @@ -60,6 +60,10 @@ mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS # Globally initialize Cyrus SASL configuration _cyrusSetup('sasl_conf') +def wait_listening(proc): + m = proc.wait_re(".*listening on ([0-9]+)$") + return m.group(1), m.group(0)+"\n" # Return (port, line) + class BrokerTestCase(ProcTestCase): """ ExampleTest that starts a broker in setUpClass and kills it in tearDownClass. @@ -68,10 +72,9 @@ class BrokerTestCase(ProcTestCase): @classmethod def setUpClass(cls): cls.broker = None # In case Proc throws, create the attribute. - with TestPort() as tp: - cls.addr = "%s:%s/example" % (tp.host, tp.port) - cls.broker = Proc([cls.broker_exe, "-a", tp.addr]) - cls.broker.wait_re("listening") + cls.broker = Proc([cls.broker_exe, "-a", "//:0"]) + cls.port, line = wait_listening(cls.broker) + cls.addr = "//:%s/example" % cls.port @classmethod def tearDownClass(cls): @@ -92,9 +95,8 @@ All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES, And the mome raths outgrabe. => AND THE MOME RATHS OUTGRABE. """ -def recv_expect(name, addr): - return "%s listening on %s\n%s" % ( - name, addr, "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])) +def recv_expect(): + return "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)]) class ContainerExampleTest(BrokerTestCase): """Run the container examples, verify they behave as expected.""" @@ -105,37 +107,30 @@ class ContainerExampleTest(BrokerTestCase): self.assertMultiLineEqual('Hello World!\n', self.proc(["helloworld", self.addr]).wait_exit()) def test_simple_send_recv(self): - self.assertMultiLineEqual("all messages confirmed\n", - self.proc(["simple_send", "-a", self.addr]).wait_exit()) - self.assertMultiLineEqual(recv_expect("simple_recv", self.addr), self.proc(["simple_recv", "-a", self.addr]).wait_exit()) + self.assertMultiLineEqual("all messages confirmed\n", self.proc(["simple_send", "-a", self.addr]).wait_exit()) + self.assertMultiLineEqual(recv_expect(), self.proc(["simple_recv", "-a", self.addr]).wait_exit()) def test_simple_recv_send(self): # Start receiver first, then run sender""" recv = self.proc(["simple_recv", "-a", self.addr]) - self.assertMultiLineEqual("all messages confirmed\n", - self.proc(["simple_send", "-a", self.addr]).wait_exit()) - self.assertMultiLineEqual(recv_expect("simple_recv", self.addr), recv.wait_exit()) + self.assertMultiLineEqual("all messages confirmed\n", self.proc(["simple_send", "-a", self.addr]).wait_exit()) + self.assertMultiLineEqual(recv_expect(), recv.wait_exit()) def test_simple_send_direct_recv(self): - with TestPort() as tp: - addr = "%s/examples" % tp.addr - recv = self.proc(["direct_recv", "-a", addr]) - recv.wait_re("listening") - self.assertMultiLineEqual("all messages confirmed\n", - self.proc(["simple_send", "-a", addr]).wait_exit()) - self.assertMultiLineEqual(recv_expect("direct_recv", addr), recv.wait_exit()) + recv = self.proc(["direct_recv", "-a", "//:0"]) + port, line = wait_listening(recv) + addr = "//:%s/examples" % port + self.assertMultiLineEqual("all messages confirmed\n", + self.proc(["simple_send", "-a", addr]).wait_exit()) + self.assertMultiLineEqual(line+recv_expect(), recv.wait_exit()) def test_simple_recv_direct_send(self): - with TestPort() as tp: - addr = "%s/examples" % tp.addr - send = self.proc(["direct_send", "-a", addr]) - send.wait_re("listening") - self.assertMultiLineEqual(recv_expect("simple_recv", addr), - self.proc(["simple_recv", "-a", addr]).wait_exit()) - self.assertMultiLineEqual( - "direct_send listening on %s\nall messages confirmed\n" % addr, - send.wait_exit()) + send = self.proc(["direct_send", "-a", "//:0"]) + port, line = wait_listening(send) + addr = "//:%s/examples" % port + self.assertMultiLineEqual(recv_expect(), self.proc(["simple_recv", "-a", addr]).wait_exit()) + self.assertMultiLineEqual(line+"all messages confirmed\n", send.wait_exit()) def test_request_response(self): server = self.proc(["server", self.addr, "example"]) # self.addr has the connection info @@ -144,12 +139,10 @@ class ContainerExampleTest(BrokerTestCase): self.proc(["client", "-a", self.addr]).wait_exit()) def test_request_response_direct(self): - with TestPort() as tp: - addr = "%s/examples" % tp.addr - server = self.proc(["server_direct", "-a", addr]) - server.wait_re("listening") - self.assertMultiLineEqual(CLIENT_EXPECT, - self.proc(["client", "-a", addr]).wait_exit()) + server = self.proc(["server_direct", "-a", "//:0"]) + port, line = wait_listening(server); + addr = "//:%s/examples" % port + self.assertMultiLineEqual(CLIENT_EXPECT, self.proc(["client", "-a", addr]).wait_exit()) def test_flow_control(self): want="""success: Example 1: simple credit @@ -157,8 +150,7 @@ success: Example 2: basic drain success: Example 3: drain without credit success: Example 4: high/low watermark """ - with TestPort() as tp: - self.assertMultiLineEqual(want, self.proc(["flow_control", "--address", tp.addr, "--quiet"]).wait_exit()) + self.assertMultiLineEqual(want, self.proc(["flow_control", "--quiet"]).wait_exit()) def test_encode_decode(self): want=""" @@ -242,33 +234,23 @@ class ContainerExampleSSLTest(BrokerTestCase): def test_ssl(self): # SSL without SASL, VERIFY_PEER_NAME - with TestPort() as tp: - addr = "amqps://%s/examples" % tp.addr - # Disable valgrind when using OpenSSL - out = self.proc(["ssl", "-a", addr, "-c", self.ssl_certs_dir()]).wait_exit() - expect = "Outgoing client connection connected via SSL. Server certificate identity CN=test_server\nHello World!" - expect_found = (out.find(expect) >= 0) - self.assertEqual(expect_found, True) + # Disable valgrind when using OpenSSL + out = self.proc(["ssl", "-c", self.ssl_certs_dir()]).wait_exit() + expect = "Server certificate identity CN=test_server\nHello World!" + self.assertIn(expect, out) def test_ssl_no_name(self): # VERIFY_PEER - with TestPort() as tp: - addr = "amqps://%s/examples" % tp.addr - # Disable valgrind when using OpenSSL - out = self.proc(["ssl", "-a", addr, "-c", self.ssl_certs_dir(), "-v", "noname"], valgrind=False).wait_exit() - expect = "Outgoing client connection connected via SSL. Server certificate identity CN=test_server\nHello World!" - expect_found = (out.find(expect) >= 0) - self.assertEqual(expect_found, True) + # Disable valgrind when using OpenSSL + out = self.proc(["ssl", "-c", self.ssl_certs_dir(), "-v", "noname"], valgrind=False).wait_exit() + expect = "Outgoing client connection connected via SSL. Server certificate identity CN=test_server\nHello World!" + self.assertIn(expect, out) def test_ssl_bad_name(self): # VERIFY_PEER - with TestPort() as tp: - addr = "amqps://%s/examples" % tp.addr - # Disable valgrind when using OpenSSL - out = self.proc(["ssl", "-a", addr, "-c", self.ssl_certs_dir(), "-v", "fail"]).wait_exit() - expect = "Expected failure of connection with wrong peer name" - expect_found = (out.find(expect) >= 0) - self.assertEqual(expect_found, True) + out = self.proc(["ssl", "-c", self.ssl_certs_dir(), "-v", "fail"]).wait_exit() + expect = "Expected failure of connection with wrong peer name" + self.assertIn(expect, out) def test_ssl_client_cert(self): # SSL with SASL EXTERNAL @@ -276,12 +258,9 @@ class ContainerExampleSSLTest(BrokerTestCase): Outgoing client connection connected via SSL. Server certificate identity CN=test_server Hello World! """ - with TestPort() as tp: - addr = "amqps://%s/examples" % tp.addr - # Disable valgrind when using OpenSSL - out = self.proc(["ssl_client_cert", addr, self.ssl_certs_dir()]).wait_exit() - expect_found = (out.find(expect) >= 0) - self.assertEqual(expect_found, True) + # Disable valgrind when using OpenSSL + out = self.proc(["ssl_client_cert", self.ssl_certs_dir()]).wait_exit() + self.assertIn(expect, out) if __name__ == "__main__": unittest.main() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/flow_control.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/flow_control.cpp b/examples/cpp/flow_control.cpp index f27b6f4..4c97344 100644 --- a/examples/cpp/flow_control.cpp +++ b/examples/cpp/flow_control.cpp @@ -195,17 +195,19 @@ class flow_receiver : public proton::messaging_handler { class flow_control : public proton::messaging_handler { private: - std::string url; proton::listener listener; flow_sender send_handler; flow_receiver receive_handler; public: - flow_control(const std::string& u) : url(u), receive_handler(send_handler) {} + flow_control() : receive_handler(send_handler) {} void on_container_start(proton::container &c) OVERRIDE { - listener = c.listen(url, proton::connection_options().handler(send_handler)); - c.connect(url); + // Listen on a dynamic port on the local host. + listener = c.listen("//:0", proton::connection_options().handler(send_handler)); + std::ostringstream url; + url << "//:" << listener.port() << "/example"; // Connect to the actual listening port + c.connect(url.str()); } void on_connection_open(proton::connection &c) OVERRIDE { @@ -223,11 +225,9 @@ class flow_control : public proton::messaging_handler { int main(int argc, char **argv) { // Pick an "unusual" port since we are going to be talking to // ourselves, not a broker. - std::string address("127.0.0.1:8888"); bool quiet = false; example::options opts(argc, argv); - opts.add_value(address, 'a', "address", "connect and send to URL", "URL"); opts.add_flag(quiet, 'q', "quiet", "suppress additional commentary of credit allocation and consumption"); try { @@ -235,7 +235,7 @@ int main(int argc, char **argv) { if (quiet) verbose = false; - flow_control fc(address); + flow_control fc; proton::container(fc).run(); return 0; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/server_direct.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/server_direct.cpp b/examples/cpp/server_direct.cpp index 3bfd60a..cf3447c 100644 --- a/examples/cpp/server_direct.cpp +++ b/examples/cpp/server_direct.cpp @@ -50,8 +50,8 @@ class server : public proton::messaging_handler { server(const std::string &u) : url(u), address_counter(0) {} void on_container_start(proton::container &c) OVERRIDE { - c.listen(url); - std::cout << "server listening on " << url << std::endl; + proton::listener l = c.listen(url); + std::cout << "server listening on " << l.port() << std::endl; } std::string to_upper(const std::string &s) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/simple_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/simple_recv.cpp b/examples/cpp/simple_recv.cpp index 39b4dfd..5a7cde4 100644 --- a/examples/cpp/simple_recv.cpp +++ b/examples/cpp/simple_recv.cpp @@ -54,7 +54,6 @@ class simple_recv : public proton::messaging_handler { if (!user.empty()) co.user(user); if (!password.empty()) co.password(password); receiver = c.open_receiver(url, co); - std::cout << "simple_recv listening on " << url << std::endl; } void on_message(proton::delivery &d, proton::message &msg) OVERRIDE { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/ssl.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/ssl.cpp b/examples/cpp/ssl.cpp index d93454f..8979ecb 100644 --- a/examples/cpp/ssl.cpp +++ b/examples/cpp/ssl.cpp @@ -80,12 +80,9 @@ struct server_handler : public proton::messaging_handler { class hello_world_direct : public proton::messaging_handler { private: - std::string url; server_handler s_handler; public: - hello_world_direct(const std::string& u) : url(u) {} - void on_container_start(proton::container &c) OVERRIDE { // Configure listener. Details vary by platform. ssl_certificate server_cert = platform_certificate("tserver", "tserverpw"); @@ -116,8 +113,10 @@ class hello_world_direct : public proton::messaging_handler { } else throw std::logic_error("bad verify mode: " + verify); c.client_connection_options(client_opts); - s_handler.listener = c.listen(url); - c.open_sender(url); + s_handler.listener = c.listen("//:0"); // Listen on port 0 to get a dynamic port + std::ostringstream url; + url << "//:" << s_handler.listener.port() << "/example"; // Connect to the actual port + c.open_sender(url.str()); } void on_connection_open(proton::connection &c) OVERRIDE { @@ -150,12 +149,7 @@ class hello_world_direct : public proton::messaging_handler { }; int main(int argc, char **argv) { - // Pick an "unusual" port since we are going to be talking to - // ourselves, not a broker. - // Note the use of "amqps" as the URL scheme to denote a TLS/SSL connection. - std::string address("amqps://127.0.0.1:8888/examples"); example::options opts(argc, argv); - opts.add_value(address, 'a', "address", "connect and send to URL", "URL"); opts.add_value(cert_directory, 'c', "cert_directory", "directory containing SSL certificates and private key information", "CERTDIR"); opts.add_value(verify, 'v', "verify", "verify type: \"minimum\", \"full\", \"fail\"", "VERIFY"); @@ -171,7 +165,7 @@ int main(int argc, char **argv) { if (verify != verify_noname && verify != verify_full && verify != verify_fail) throw std::runtime_error("bad verify argument: " + verify); - hello_world_direct hwd(address); + hello_world_direct hwd; proton::container(hwd).run(); return 0; } catch (const std::exception& e) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/examples/cpp/ssl_client_cert.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/ssl_client_cert.cpp b/examples/cpp/ssl_client_cert.cpp index 32a9a1d..792a6c7 100644 --- a/examples/cpp/ssl_client_cert.cpp +++ b/examples/cpp/ssl_client_cert.cpp @@ -31,6 +31,7 @@ #include <proton/transport.hpp> #include <iostream> +#include <sstream> #include "fake_cpp11.hpp" @@ -76,11 +77,9 @@ struct server_handler : public proton::messaging_handler { class hello_world_direct : public proton::messaging_handler { private: - std::string url; server_handler s_handler; public: - hello_world_direct(const std::string& u) : url(u) {} void on_container_start(proton::container &c) OVERRIDE { // Configure listener. Details vary by platform. @@ -103,8 +102,10 @@ class hello_world_direct : public proton::messaging_handler { client_opts.ssl_client_options(ssl_cli).sasl_allowed_mechs("EXTERNAL"); c.client_connection_options(client_opts); - s_handler.listener = c.listen(url); - c.open_sender(url); + s_handler.listener = c.listen("//:0"); + std::ostringstream url; + url << "//:" << s_handler.listener.port() << "/example"; // Connect to the actual port + c.open_sender(url.str()); } void on_connection_open(proton::connection &c) OVERRIDE { @@ -128,19 +129,16 @@ class hello_world_direct : public proton::messaging_handler { int main(int argc, char **argv) { try { - // Pick an "unusual" port since we are going to be talking to ourselves, not a broker. - // Note the use of "amqps" as the URL scheme to denote a TLS/SSL connection. - std::string url = argc > 1 ? argv[1] : "amqps://127.0.0.1:8888/examples"; // Location of certificates and private key information: - if (argc > 2) { - cert_directory = argv[2]; + if (argc > 1) { + cert_directory = argv[1]; size_t sz = cert_directory.size(); if (sz && cert_directory[sz -1] != '/') cert_directory.append("/"); + } else { + cert_directory = "ssl_certs/"; } - else cert_directory = "ssl_certs/"; - - hello_world_direct hwd(url); + hello_world_direct hwd; proton::container(hwd).run(); return 0; } catch (const std::exception& e) { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/proton-c/bindings/cpp/include/proton/listener.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/listener.hpp b/proton-c/bindings/cpp/include/proton/listener.hpp index f344892..f1ca9ac 100644 --- a/proton-c/bindings/cpp/include/proton/listener.hpp +++ b/proton-c/bindings/cpp/include/proton/listener.hpp @@ -51,6 +51,11 @@ class PN_CPP_CLASS_EXTERN listener { /// container::listen that returned this listener. PN_CPP_EXTERN void stop(); + /// Return the port used by the listener. + /// If port 0 was passed to container::listen, this will be a dynamically allocated port. + /// @throw proton::error if the listener does not have a port + PN_CPP_EXTERN int port(); + private: pn_listener_t* listener_; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/proton-c/bindings/cpp/src/container_test.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/container_test.cpp b/proton-c/bindings/cpp/src/container_test.cpp index c0a9734..93733a5 100644 --- a/proton-c/bindings/cpp/src/container_test.cpp +++ b/proton-c/bindings/cpp/src/container_test.cpp @@ -19,7 +19,6 @@ #include "test_bits.hpp" -#include "test_port.hpp" #include "proton/connection.hpp" #include "proton/connection_options.hpp" @@ -37,6 +36,11 @@ namespace { +std::string make_url(std::string host, int port) { + std::ostringstream url; + url << "//" << host << ":" << port; + return url.str(); +} struct test_listen_handler : public proton::listen_handler { bool on_open_, on_accept_, on_close_; @@ -72,7 +76,6 @@ class test_handler : public proton::messaging_handler { std::string peer_vhost; std::string peer_container_id; - test_port port; proton::listener listener; test_listen_handler listen_handler; @@ -81,8 +84,8 @@ class test_handler : public proton::messaging_handler { {} void on_container_start(proton::container &c) PN_CPP_OVERRIDE { - listener = c.listen(port.url(), listen_handler); - proton::connection conn = c.connect(port.url(host), opts); + listener = c.listen("//:0", listen_handler); + proton::connection conn = c.connect(make_url(host, listener.port()), opts); } void on_connection_open(proton::connection &c) PN_CPP_OVERRIDE { @@ -164,14 +167,13 @@ int test_container_bad_address() { } class stop_tester : public proton::messaging_handler { - test_port port; proton::listener listener; // Set up a listener which would block forever void on_container_start(proton::container& c) PN_CPP_OVERRIDE { ASSERT(state==0); - listener = c.listen(port.url()); - c.connect(port.url()); + listener = c.listen("//localhost:0"); + c.connect(make_url("", listener.port())); c.auto_stop(false); state = 1; } @@ -213,17 +215,16 @@ int test_container_stop() { struct hang_tester : public proton::messaging_handler { proton::listener listener; - test_port port; bool done; hang_tester() : done(false) {} void connect(proton::container* c) { - c->connect(port.url()); + c->connect(make_url("", listener.port())); } void on_container_start(proton::container& c) PN_CPP_OVERRIDE { - listener = c.listen(port.url()); + listener = c.listen("//:0"); c.schedule(proton::duration(250), make_work(&hang_tester::connect, this, &c)); } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/proton-c/bindings/cpp/src/listener.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/listener.cpp b/proton-c/bindings/cpp/src/listener.cpp index 53f238c..7effbf4 100644 --- a/proton-c/bindings/cpp/src/listener.cpp +++ b/proton-c/bindings/cpp/src/listener.cpp @@ -22,6 +22,7 @@ #include "proton/listen_handler.hpp" #include <proton/listener.h> +#include <proton/netaddr.h> #include "contexts.hpp" @@ -33,8 +34,17 @@ listener::listener(pn_listener_t* l): listener_(l) {} listener::listener(const listener& l) : listener_(l.listener_) {} listener::~listener() {} listener& listener::operator=(const listener& l) { listener_ = l.listener_; return *this; } + void listener::stop() { if (listener_) pn_listener_close(listener_); } +int listener::port() { + char port[16] = "invalid"; + pn_netaddr_host_port(pn_netaddr_listening(listener_), NULL, 0, port, sizeof(port)); + int i = atoi(port); + if (!i) throw error("listener has no port"); + return i; +} + listen_handler::~listen_handler() {} void listen_handler::on_open(listener&) {} connection_options listen_handler::on_accept(listener&) { return connection_options(); } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/proton-c/bindings/cpp/src/proactor_container_impl.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp index 3e68c44..188a8d6 100644 --- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp +++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp @@ -367,7 +367,7 @@ pn_listener_t* container::impl::listen_common_lh(const std::string& addr) { if (stopping_) throw proton::error("container is stopping"); - proton::url url(addr); + proton::url url(addr, false); // Don't want un-helpful defaults like "localhost" // Figure out correct string len then create connection address int len = pn_proactor_addr(0, 0, url.host().c_str(), url.port().c_str()); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/proton-c/bindings/cpp/src/test_port.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/test_port.hpp b/proton-c/bindings/cpp/src/test_port.hpp deleted file mode 100644 index cc592fa..0000000 --- a/proton-c/bindings/cpp/src/test_port.hpp +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef TEST_PORT_HPP -#define TEST_PORT_HPP - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <cstring> -#include <cerrno> - -/* Some simple platform-secifics to acquire an unused socket */ - -#if defined(_WIN32) - -extern "C" { -# include <winsock2.h> -# include <ws2tcpip.h> -} - -typedef SOCKET sock_t; - -void check_err(int ret, const char *what) { - if (ret) { - char buf[512]; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, WSAGetLastError(), NULL, buf, sizeof(buf), NULL); - fprintf(stderr, "%s: %s\n", what, buf); - throw std::runtime_error(buf); - } -} - -class test_socket { - public: - SOCKET sock_; - test_socket() { - WORD wsa_ver = MAKEWORD(2, 2); - WSADATA unused; - check_err(WSAStartup(wsa_ver, &unused), "WSAStartup"); - sock_ = socket(AF_INET, SOCK_STREAM, 0); - check_err(sock_ < 0, "socket"); - } - ~test_socket() { WSACleanup(); } - void close_early() { closesocket(sock_); } // Windows won't allow two sockets on a port -}; - -#elif defined(__APPLE__) || defined(__FreeBSD__) - -// BSD derivatives don't support the same SO_REUSEADDR semantics as Linux so -// do the same thing as windows and hope for the best -extern "C" { -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <unistd.h> -# include <netdb.h> -} - -void check_err(int ret, const std::string& what) { - if (ret) throw std::runtime_error(what + ": " + std::strerror(errno)); -} - -class test_socket { - public: - int sock_; - test_socket() : sock_(socket(AF_INET, SOCK_STREAM, 0)) { - check_err(sock_ < 0, "socket"); - int on = 1; - check_err(setsockopt(sock_, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)), - "setsockop"); - } - ~test_socket() { } - void close_early() { - close(sock_); - } -}; - -#else /* POSIX */ - -extern "C" { -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <unistd.h> -# include <netdb.h> -} - -void check_err(int ret, const std::string& what) { - if (ret) throw std::runtime_error(what + ": " + std::strerror(errno)); -} - -class test_socket { - public: - int sock_; - test_socket() : sock_(socket(AF_INET, SOCK_STREAM, 0)) { - check_err(sock_ < 0, "socket"); - int on = 1; - check_err(setsockopt(sock_, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)), - "setsockop"); - } - ~test_socket() { close(sock_); } - void close_early() {} // Don't close early on POSIX, keep the port safe -}; - -#endif - -#define TEST_PORT_MAX_STR 1060 - -/* Acquire a port suitable for listening */ -class test_port { - test_socket sock_; - int port_; - - public: - - /* Acquire a port suitable for listening */ - test_port() : port_(0) { - /* Create a socket and bind(INADDR_LOOPBACK:0) to get a free port. - Set socket options so the port can be bound and used for listen() within this process, - even though it is bound to the test_port socket. - Use host to create the host_port address string. - */ - struct sockaddr_in addr = {0}; - addr.sin_family = AF_INET; /* set the type of connection to TCP/IP */ - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = 0; /* bind to port 0 */ - check_err(bind(sock_.sock_, (struct sockaddr*)&addr, sizeof(addr)), "bind"); - socklen_t len = sizeof(addr); - check_err(getsockname(sock_.sock_, (struct sockaddr*)&addr, &len), "getsockname"); - port_ = ntohs(addr.sin_port); - sock_.close_early(); - } - - int port() const { return port_; } - - std::string url(const std::string& host="") const { - std::ostringstream url; - url << "amqp://" << host << ":" << port_; - return url.str(); - } -}; - - - -#endif // TEST_PORT_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d6cef7b8/tools/py/proctest.py ---------------------------------------------------------------------- diff --git a/tools/py/proctest.py b/tools/py/proctest.py index 33cf26e..940ffe7 100644 --- a/tools/py/proctest.py +++ b/tools/py/proctest.py @@ -33,27 +33,6 @@ from os.path import dirname as dirname DEFAULT_TIMEOUT=10 -class TestPort(object): - """Get an unused port using bind(0) and SO_REUSEADDR and hold it till close() - Can be used as `with TestPort() as tp:` Provides tp.host, tp.port and tp.addr - (a "host:port" string) - """ - def __init__(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.sock.bind(('127.0.0.1', 0)) # Testing examples is local only - self.host, self.port = socket.getnameinfo(self.sock.getsockname(), 0) - self.addr = "%s:%s" % (self.host, self.port) - - def __enter__(self): - return self - - def __exit__(self, *args): - self.close() - - def close(self): - self.sock.close() - class ProcError(Exception): """An exception that displays failed process output""" def __init__(self, proc, what="bad exit status"): --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
