/* Close the transport to abort a connection, i.e. close the socket without an AMQP close */ static pn_event_type_t listen_abort_handler(test_handler_t *th, pn_event_t *e) { switch (pn_event_type(e)) { case PN_CONNECTION_REMOTE_OPEN: /* Close the transport - abruptly closes the socket */ pn_transport_close_tail(pn_connection_transport(pn_event_connection(e))); pn_transport_close_head(pn_connection_transport(pn_event_connection(e))); return PN_EVENT_NONE; default: /* Don't auto-close the listener to keep the event sequences simple */ return listen_handler(th, e); } }
static void test_netaddr(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; /* Use IPv4 to get consistent results all platforms */ pn_listener_t *l = test_listen(&tps[1], "127.0.0.1"); pn_connection_t *c = pn_connection(); pn_proactor_connect2(client, c, NULL, listener_info(l).connect); if (!TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps))) { TEST_COND_EMPTY(t, last_condition); /* Show the last condition */ return; /* don't continue if connection is closed */ } /* client remote, client local, server remote and server local address strings */ char cr[1024], cl[1024], sr[1024], sl[1024]; pn_transport_t *ct = pn_connection_transport(c); const pn_netaddr_t *na = pn_transport_remote_addr(ct); pn_netaddr_str(na, cr, sizeof(cr)); TEST_STR_IN(t, listener_info(l).port, cr); /* remote address has listening port */ pn_connection_t *s = last_accepted; /* server side of the connection */ pn_transport_t *st = pn_connection_transport(s); if (!TEST_CHECK(t, st)) return; pn_netaddr_str(pn_transport_local_addr(st), sl, sizeof(sl)); TEST_STR_EQUAL(t, cr, sl); /* client remote == server local */ pn_netaddr_str(pn_transport_local_addr(ct), cl, sizeof(cl)); pn_netaddr_str(pn_transport_remote_addr(st), sr, sizeof(sr)); TEST_STR_EQUAL(t, cl, sr); /* client local == server remote */ char host[MAX_STR] = ""; char serv[MAX_STR] = ""; int err = pn_netaddr_host_port(na, host, sizeof(host), serv, sizeof(serv)); TEST_CHECK(t, 0 == err); TEST_STR_EQUAL(t, "127.0.0.1", host); TEST_STR_EQUAL(t, listener_info(l).port, serv); /* Make sure you can use NULL, 0 to get length of address string without a crash */ size_t len = pn_netaddr_str(pn_transport_local_addr(ct), NULL, 0); TEST_CHECKF(t, strlen(cl) == len, "%d != %d", strlen(cl), len); TEST_PROACTORS_DRAIN(tps); TEST_PROACTORS_DESTROY(tps); }
void qd_policy_amqp_open(void *context, bool discard) { qd_connection_t *qd_conn = (qd_connection_t *)context; if (!discard) { pn_connection_t *conn = qd_connection_pn(qd_conn); qd_dispatch_t *qd = qd_conn->server->qd; qd_policy_t *policy = qd->policy; bool connection_allowed = true; if (policy->enableAccessRules) { // Open connection or not based on policy. pn_transport_t *pn_trans = pn_connection_transport(conn); const char *hostip = qdpn_connector_hostip(qd_conn->pn_cxtr); const char *pcrh = pn_connection_remote_hostname(conn); const char *app = (pcrh ? pcrh : ""); const char *conn_name = qdpn_connector_name(qd_conn->pn_cxtr); #define SETTINGS_NAME_SIZE 256 char settings_name[SETTINGS_NAME_SIZE]; uint32_t conn_id = qd_conn->connection_id; qd_conn->policy_settings = NEW(qd_policy_settings_t); // TODO: memory pool for settings memset(qd_conn->policy_settings, 0, sizeof(qd_policy_settings_t)); if (qd_policy_open_lookup_user(policy, qd_conn->user_id, hostip, app, conn_name, settings_name, SETTINGS_NAME_SIZE, conn_id, qd_conn->policy_settings) && settings_name[0]) { // This connection is allowed by policy. // Apply transport policy settings if (qd_conn->policy_settings->maxFrameSize > 0) pn_transport_set_max_frame(pn_trans, qd_conn->policy_settings->maxFrameSize); if (qd_conn->policy_settings->maxSessions > 0) pn_transport_set_channel_max(pn_trans, qd_conn->policy_settings->maxSessions - 1); } else { // This connection is denied by policy. connection_allowed = false; } } else { // No policy implies automatic policy allow // Note that connections not governed by policy have no policy_settings. } if (connection_allowed) { if (pn_connection_state(conn) & PN_LOCAL_UNINIT) pn_connection_open(conn); policy_notify_opened(qd_conn->open_container, qd_conn, qd_conn->context); } else { qd_policy_private_deny_amqp_connection(conn, RESOURCE_LIMIT_EXCEEDED, CONNECTION_DISALLOWED); } } qd_connection_set_event_stall(qd_conn, false); }
uint32_t connection::idle_timeout() const { return pn_transport_get_remote_idle_timeout(pn_connection_transport(pn_object())); }
transport connection::transport() const { return make_wrapper(pn_connection_transport(pn_object())); }
uint16_t connection::max_sessions() const { return pn_transport_remote_channel_max(pn_connection_transport(pn_object())); }
uint32_t connection::max_frame_size() const { return pn_transport_get_remote_max_frame(pn_connection_transport(pn_object())); }
transport &connection::transport() { return *transport::cast(pn_connection_transport(pn_cast(this))); }
std::string connection::user() const { return str(pn_transport_get_user(pn_connection_transport(pn_object()))); }
void apply(connection& c) { pn_connection_t *pnc = connection_options::pn_connection(c); pn_transport_t *pnt = pn_connection_transport(pnc); connector *outbound = dynamic_cast<connector*>( connection_context::get(c).handler.get()); bool uninit = (c.state() & endpoint::LOCAL_UNINIT); // pnt is NULL between reconnect attempts. // Only apply transport options if uninit or outbound with // transport not yet configured. if (pnt && (uninit || (outbound && !outbound->transport_configured()))) { // SSL if (outbound && outbound->address().scheme() == url::AMQPS) { pn_ssl_t *ssl = pn_ssl(pnt); if (pn_ssl_init(ssl, ssl_client_options.value.pn_domain(), NULL)) throw error(MSG("client SSL/TLS initialization error")); } else if (!outbound) { pn_acceptor_t *pnp = pn_connection_acceptor(pnc); if (pnp) { listener_context &lc(listener_context::get(pnp)); if (lc.ssl) { pn_ssl_t *ssl = pn_ssl(pnt); if (pn_ssl_init(ssl, ssl_server_options.value.pn_domain(), NULL)) throw error(MSG("server SSL/TLS initialization error")); } } } // SASL transport t = c.transport(); if (!sasl_enabled.set || sasl_enabled.value) { if (sasl_enabled.set) // Explicitly set, not just default behaviour. t.sasl(); // Force a sasl instance. Lazily create one otherwise. if (sasl_allow_insecure_mechs.set) t.sasl().allow_insecure_mechs(sasl_allow_insecure_mechs.value); if (sasl_allowed_mechs.set) t.sasl().allowed_mechs(sasl_allowed_mechs.value); if (sasl_config_name.set) t.sasl().config_name(sasl_config_name.value); if (sasl_config_path.set) t.sasl().config_path(sasl_config_path.value); } if (max_frame_size.set) pn_transport_set_max_frame(pnt, max_frame_size.value); if (max_channels.set) pn_transport_set_channel_max(pnt, max_channels.value); if (idle_timeout.set) pn_transport_set_idle_timeout(pnt, idle_timeout.value.ms()); } // Only apply connection options if uninit. if (uninit) { if (reconnect.set && outbound) outbound->reconnect_timer(reconnect.value); if (container_id.set) pn_connection_set_container(pnc, container_id.value.c_str()); if (link_prefix.set) connection_context::get(pnc).link_gen.prefix(link_prefix.value); } }