/* Tests for error handling */ static void test_errors(test_t *t) { test_proactor_t tps[] = { test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) }; pn_proactor_t *client = tps[0].proactor, *server = tps[1].proactor; /* Invalid connect/listen service name */ pn_connection_t *c = pn_connection(); pn_proactor_connect2(client, c, NULL, "127.0.0.1:xxx"); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); TEST_COND_DESC(t, "xxx", last_condition); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); pn_proactor_listen(server, pn_listener(), "127.0.0.1:xxx", 1); TEST_PROACTORS_RUN(tps); TEST_HANDLER_EXPECT(&tps[1].handler, PN_LISTENER_CLOSE, 0); /* CLOSE only, no OPEN */ TEST_COND_DESC(t, "xxx", last_condition); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); /* Invalid connect/listen host name */ c = pn_connection(); pn_proactor_connect2(client, c, NULL, "nosuch.example.com:"); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); TEST_COND_DESC(t, "nosuch", last_condition); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); test_handler_clear(&tps[1].handler, 0); pn_proactor_listen(server, pn_listener(), "nosuch.example.com:", 1); TEST_PROACTORS_RUN(tps); TEST_HANDLER_EXPECT(&tps[1].handler, PN_LISTENER_CLOSE, 0); /* CLOSE only, no OPEN */ TEST_COND_DESC(t, "nosuch", last_condition); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); /* Listen on a port already in use */ pn_listener_t *l = pn_listener(); pn_proactor_listen(server, l, ":0", 1); TEST_ETYPE_EQUAL(t, PN_LISTENER_OPEN, TEST_PROACTORS_RUN(tps)); test_handler_clear(&tps[1].handler, 0); struct addrinfo laddr = listener_info(l); pn_proactor_listen(server, pn_listener(), laddr.connect, 1); /* Busy */ TEST_PROACTORS_RUN(tps); TEST_HANDLER_EXPECT(&tps[1].handler, PN_LISTENER_CLOSE, 0); /* CLOSE only, no OPEN */ TEST_COND_NAME(t, "proton:io", last_condition); pn_listener_close(l); TEST_ETYPE_EQUAL(t, PN_LISTENER_CLOSE, TEST_PROACTORS_RUN(tps)); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); /* Connect with no listener */ c = pn_connection(); pn_proactor_connect2(client, c, NULL, laddr.connect); if (TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps))) { TEST_COND_DESC(t, "refused", last_condition); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); } TEST_PROACTORS_DESTROY(tps); }
/* Make sure we clean up released connections and open sockets correctly */ static void test_release_free(test_t *t) { test_proactor_t tps[] = { test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) }; pn_proactor_t *client = tps[0].proactor; pn_listener_t *l = test_listen(&tps[1], ""); /* leave one connection to the proactor */ pn_proactor_connect2(client, NULL, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); /* release c1 and free immediately */ pn_connection_t *c1 = pn_connection(); pn_proactor_connect2(client, c1, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); pn_proactor_release_connection(c1); /* We free but socket should still be cleaned up */ pn_connection_free(c1); TEST_CHECK(t, pn_proactor_get(client) == NULL); /* Should be idle */ TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* Server closed */ /* release c2 and but don't free till after proactor free */ pn_connection_t *c2 = pn_connection(); pn_proactor_connect2(client, c2, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); pn_proactor_release_connection(c2); TEST_CHECK(t, pn_proactor_get(client) == NULL); /* Should be idle */ TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* Server closed */ TEST_PROACTORS_DESTROY(tps); pn_connection_free(c2); /* Check freeing a listener or connection that was never given to a proactor */ pn_listener_free(pn_listener()); pn_connection_free(pn_connection()); }
/* Return a pn_listener_t*, raise errors if not successful */ pn_listener_t *test_listen(test_proactor_t *tp, const char *host) { char addr[1024]; pn_listener_t *l = pn_listener(); (void)pn_proactor_addr(addr, sizeof(addr), host, "0"); pn_proactor_listen(tp->proactor, l, addr, 4); TEST_ETYPE_EQUAL(tp->handler.t, PN_LISTENER_OPEN, test_proactors_run(tp, 1)); TEST_COND_EMPTY(tp->handler.t, last_condition); return l; }
/* Test that we can control listen/select on ipv6/v4 and listen on both by default */ static void test_ipv4_ipv6(test_t *t) { test_proactor_t tps[] ={ test_proactor(t, open_close_handler), test_proactor(t, listen_handler) }; pn_proactor_t *client = tps[0].proactor, *server = tps[1].proactor; /* Listen on all interfaces for IPv4 only. */ pn_listener_t *l4 = test_listen(&tps[1], "0.0.0.0"); TEST_PROACTORS_DRAIN(tps); /* Empty address listens on both IPv4 and IPv6 on all interfaces */ pn_listener_t *l = test_listen(&tps[1], ""); TEST_PROACTORS_DRAIN(tps); #define EXPECT_CONNECT(LISTENER, HOST) do { \ char addr[1024]; \ pn_proactor_addr(addr, sizeof(addr), HOST, listener_info(LISTENER).port); \ pn_proactor_connect2(client, NULL, NULL, addr); \ TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); \ TEST_COND_EMPTY(t, last_condition); \ TEST_PROACTORS_DRAIN(tps); \ } while(0) EXPECT_CONNECT(l4, "127.0.0.1"); /* v4->v4 */ EXPECT_CONNECT(l4, ""); /* local->v4*/ EXPECT_CONNECT(l, "127.0.0.1"); /* v4->all */ EXPECT_CONNECT(l, ""); /* local->all */ /* Listen on ipv6 loopback, if it fails skip ipv6 tests. NOTE: Don't use the unspecified address "::" here - ipv6-disabled platforms may allow listening on "::" without complaining. However they won't have a local ipv6 loopback configured, so "::1" will force an error. */ TEST_PROACTORS_DRAIN(tps); pn_listener_t *l6 = pn_listener(); pn_proactor_listen(server, l6, "::1:0", 4); pn_event_type_t e = TEST_PROACTORS_RUN(tps); if (e == PN_LISTENER_OPEN && !pn_condition_is_set(last_condition)) { TEST_PROACTORS_DRAIN(tps); EXPECT_CONNECT(l6, "::1"); /* v6->v6 */ EXPECT_CONNECT(l6, ""); /* local->v6 */ EXPECT_CONNECT(l, "::1"); /* v6->all */ pn_listener_close(l6); } else { const char *d = pn_condition_get_description(last_condition); TEST_LOGF(t, "skip IPv6 tests: %s %s", pn_event_type_name(e), d ? d : "no condition"); } pn_listener_close(l); pn_listener_close(l4); TEST_PROACTORS_DESTROY(tps); }
pn_listener_t *pn_messenger_isource(pn_messenger_t *messenger, const char *source) { char buf[strlen(source) + 1]; strcpy(buf, source); char *domain, *name; parse_address(buf, &domain, &name); char *user = NULL; char *pass = NULL; char *host = "0.0.0.0"; char *port = "5672"; parse_url(domain + 1, &user, &pass, &host, &port); pn_listener_t *listener = pn_listener(messenger->driver, host, port, NULL); if (listener) { messenger->listeners++; } return listener; }
int main(int argc, char **argv) { char *url = NULL; char *address = "queue"; char *mechanism = "ANONYMOUS"; int count = 1; bool quiet = false; int high = 100; int low = 50; int size = 32; int opt; while ((opt = getopt(argc, argv, "c:a:m:n:s:u:l:qhVXY")) != -1) { switch (opt) { case 'c': if (url) pn_fatal("multiple connect urls not allowed\n"); url = optarg; break; case 'a': address = optarg; break; case 'm': mechanism = optarg; break; case 'n': count = atoi(optarg); break; case 's': size = atoi(optarg); break; case 'u': high = atoi(optarg); break; case 'l': low = atoi(optarg); break; case 'q': quiet = true; break; case 'V': printf("proton version %i.%i\n", PN_VERSION_MAJOR, PN_VERSION_MINOR); exit(EXIT_SUCCESS); case 'X': value(argc, argv); exit(EXIT_SUCCESS); case 'Y': buffer(argc, argv); exit(EXIT_SUCCESS); case 'h': printf("Usage: %s [-h] [-c [user[:password]@]host[:port]] [-a <address>] [-m <sasl-mech>]\n", argv[0]); printf("\n"); printf(" -c The connect url.\n"); printf(" -a The AMQP address.\n"); printf(" -m The SASL mechanism.\n"); printf(" -n The number of messages.\n"); printf(" -s Message size.\n"); printf(" -u Upper flow threshold.\n"); printf(" -l Lower flow threshold.\n"); printf(" -q Supress printouts.\n"); printf(" -h Print this help.\n"); exit(EXIT_SUCCESS); default: /* '?' */ pn_fatal("Usage: %s -h\n", argv[0]); } } char *user = NULL; char *pass = NULL; char *host = "0.0.0.0"; char *port = "5672"; parse_url(url, &user, &pass, &host, &port); pn_driver_t *drv = pn_driver(); if (url) { struct client_context ctx = {false, false, count, count, drv, quiet, size, high, low}; ctx.username = user; ctx.password = pass; ctx.mechanism = mechanism; ctx.hostname = host; ctx.address = address; pn_connector_t *ctor = pn_connector(drv, host, port, &ctx); if (!ctor) pn_fatal("connector failed\n"); pn_connector_set_connection(ctor, pn_connection()); while (!ctx.done) { pn_driver_wait(drv, -1); pn_connector_t *c; while ((c = pn_driver_connector(drv))) { pn_connector_process(c); client_callback(c); if (pn_connector_closed(c)) { pn_connection_free(pn_connector_connection(c)); pn_connector_free(c); } else { pn_connector_process(c); } } } } else { struct server_context ctx = {0, quiet, size}; if (!pn_listener(drv, host, port, &ctx)) pn_fatal("listener failed\n"); while (true) { pn_driver_wait(drv, -1); pn_listener_t *l; pn_connector_t *c; while ((l = pn_driver_listener(drv))) { c = pn_listener_accept(l); pn_connector_set_context(c, &ctx); } while ((c = pn_driver_connector(drv))) { pn_connector_process(c); server_callback(c); if (pn_connector_closed(c)) { pn_connection_free(pn_connector_connection(c)); pn_connector_free(c); } else { pn_connector_process(c); } } } } pn_driver_free(drv); return 0; }
int main ( int argc, char ** argv ) { char info[1000]; int expected = (argc > 1) ? atoi(argv[1]) : 100000; int received = 0; int size = 32; int msg_size = 50; bool done = false; int initial_credit = 500, new_credit = 250, low_credit_limit = 250; char const * host = "0.0.0.0"; char const * port = "5672"; bool sasl_done = false; pn_driver_t * driver; pn_listener_t * listener; pn_connector_t * connector; pn_connection_t * connection; pn_session_t * session; pn_link_t * link; pn_delivery_t * delivery; char * message_data = (char *) malloc ( MY_BUF_SIZE ); int message_data_capacity = MY_BUF_SIZE; fprintf ( stderr, "drecv expecting %d messages.\n", expected ); driver = pn_driver ( ); if ( ! pn_listener(driver, host, port, 0) ) { fprintf ( stderr, "listener creation failed.\n" ); exit ( 1 ); } while ( ! done) { pn_driver_wait ( driver, -1 ); if ( (listener = pn_driver_listener(driver)) ) pn_listener_accept( listener ); if ( (connector = pn_driver_connector(driver)) ) { pn_connector_process ( connector ); if ( ! sasl_done ) if( ! (sasl_done = get_sasl_over_with(connector) )) continue; connection = pn_connector_connection ( connector ); /*========================================================= Open everything that is ready on the other side but not here. =========================================================*/ pn_state_t hes_ready_im_not = PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE; if (pn_connection_state(connection) == hes_ready_im_not) pn_connection_open( connection); for ( session = pn_session_head(connection, hes_ready_im_not); session; session = pn_session_next(session, hes_ready_im_not) ) pn_session_open(session); for ( link = pn_link_head(connection, hes_ready_im_not); link; link = pn_link_next(link, hes_ready_im_not) ) { pn_terminus_copy(pn_link_source(link), pn_link_remote_source(link)); pn_terminus_copy(pn_link_target(link), pn_link_remote_target(link)); pn_link_open ( link ); if ( pn_link_is_receiver(link) ) pn_link_flow ( link, initial_credit ); } /*========================================================== Get all available deliveries. ==========================================================*/ for ( delivery = pn_work_head ( connection ); delivery; delivery = pn_work_next ( delivery ) ) { if ( pn_delivery_readable(delivery) ) { link = pn_delivery_link ( delivery ); while ( PN_EOS != pn_link_recv(link, message_data, MY_BUF_SIZE) ) ; pn_link_advance ( link ); pn_delivery_update ( delivery, PN_ACCEPTED ); pn_delivery_settle ( delivery ); if ( ++ received >= expected ) { sprintf ( info, "received %d messages", received ); print_timestamp ( stderr, info ); done = true; } // a progress report for long tests. if ( ! (received % 5000000) ) fprintf ( stderr, "received: %d\n", received ); if ( pn_link_credit(link) <= low_credit_limit ) pn_link_flow ( link, new_credit ); } else { // TODO // Why am I getting writables? // And what to do with them? } } /*=============================================================== Shut down everything that the other side has closed. ===============================================================*/ pn_state_t active_here_closed_there = PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED; if ( pn_connection_state(connection) == active_here_closed_there ) pn_connection_close ( connection ); for ( session = pn_session_head(connection, active_here_closed_there); session; session = pn_session_next(session, active_here_closed_there) ) pn_session_close ( session ); for ( link = pn_link_head(connection, active_here_closed_there); link; link = pn_link_next(link, active_here_closed_there) ) pn_link_close ( link ); if ( pn_connector_closed(connector) ) { pn_connection_free ( pn_connector_connection(connector) ); pn_connector_free ( connector ); done = true; } else pn_connector_process(connector); } } pn_driver_free(driver); return 0; }