static void setup_outgoing_link(qd_container_t *container, pn_link_t *pn_link) { sys_mutex_lock(container->lock); qd_node_t *node = 0; const char *source = pn_terminus_get_address(pn_link_remote_source(pn_link)); qd_field_iterator_t *iter; // TODO - Extract the name from the structured source if (source) { iter = qd_address_iterator_string(source, ITER_VIEW_NODE_ID); qd_hash_retrieve(container->node_map, iter, (void*) &node); qd_field_iterator_free(iter); } sys_mutex_unlock(container->lock); if (node == 0) { if (container->default_node) node = container->default_node; else { pn_condition_t *cond = pn_link_condition(pn_link); pn_condition_set_name(cond, "amqp:not-found"); pn_condition_set_description(cond, "Source node does not exist"); pn_link_close(pn_link); return; } } qd_link_t *link = new_qd_link_t(); if (!link) { pn_condition_t *cond = pn_link_condition(pn_link); pn_condition_set_name(cond, "amqp:internal-error"); pn_condition_set_description(cond, "Insufficient memory"); pn_link_close(pn_link); return; } link->pn_sess = pn_link_session(pn_link); link->pn_link = pn_link; link->direction = QD_OUTGOING; link->context = 0; link->node = node; link->remote_snd_settle_mode = pn_link_remote_snd_settle_mode(pn_link); link->drain_mode = pn_link_get_drain(pn_link); link->close_sess_with_link = false; // // Keep the borrowed references // pn_incref(pn_link); pn_incref(link->pn_sess); pn_link_set_context(pn_link, link); node->ntype->outgoing_handler(node->context, link); }
void _qd_policy_deny_amqp_link(pn_link_t *link, qd_connection_t *qd_conn) { pn_condition_t * cond = pn_link_condition(link); (void) pn_condition_set_name( cond, RESOURCE_LIMIT_EXCEEDED); (void) pn_condition_set_description(cond, LINK_DISALLOWED); pn_link_close(link); }
static void pni_connection_writable(pn_selectable_t *sel) { pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel); pn_transport_t *transport = pni_transport(sel); ssize_t pending = pn_transport_pending(transport); if (pending > 0) { ssize_t n = pn_send(pni_reactor_io(reactor), pn_selectable_get_fd(sel), pn_transport_head(transport), pending); if (n < 0) { if (!pn_wouldblock(pni_reactor_io(reactor))) { pn_condition_t *cond = pn_transport_condition(transport); if (!pn_condition_is_set(cond)) { pn_condition_set_name(cond, "proton:io"); pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor))); } pn_transport_close_head(transport); } } else { pn_transport_pop(transport, n); } } ssize_t newpending = pn_transport_pending(transport); if (newpending != pending) { pni_connection_update(sel); pn_reactor_update(reactor, sel); } }
static void pni_connection_readable(pn_selectable_t *sel) { pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel); pn_transport_t *transport = pni_transport(sel); ssize_t capacity = pn_transport_capacity(transport); if (capacity > 0) { ssize_t n = pn_recv(pni_reactor_io(reactor), pn_selectable_get_fd(sel), pn_transport_tail(transport), capacity); if (n <= 0) { if (n == 0 || !pn_wouldblock(pni_reactor_io(reactor))) { if (n < 0) { pn_condition_t *cond = pn_transport_condition(transport); pn_condition_set_name(cond, "proton:io"); pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor))); } pn_transport_close_tail(transport); } } else { pn_transport_process(transport, (size_t)n); } } ssize_t newcap = pn_transport_capacity(transport); //occasionally transport events aren't generated when expected, so //the following hack ensures we always update the selector if (1 || newcap != capacity) { pni_connection_update(sel); pn_reactor_update(reactor, sel); } }
void qd_policy_deny_amqp_session(pn_session_t *ssn, qd_connection_t *qd_conn) { pn_condition_t * cond = pn_session_condition(ssn); (void) pn_condition_set_name( cond, RESOURCE_LIMIT_EXCEEDED); (void) pn_condition_set_description(cond, SESSION_DISALLOWED); pn_session_close(ssn); qd_conn->policy_settings->denialCounts->sessionDenied++; }
void qd_policy_private_deny_amqp_connection(pn_connection_t *conn, const char *cond_name, const char *cond_descr) { pn_condition_t * cond = pn_connection_condition(conn); (void) pn_condition_set_name( cond, cond_name); (void) pn_condition_set_description(cond, cond_descr); pn_connection_close(conn); // Connection denial counts are counted and logged by python code. }
/* Test pn_proactor_disconnect */ static void test_disconnect(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; /* Start two listeners */ pn_listener_t *l = test_listen(&tps[1], ""); pn_listener_t *l2 = test_listen(&tps[1], ""); /* Only wait for one connection to remote-open before disconnect */ pn_connection_t *c = pn_connection(); pn_proactor_connect2(client, c, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); pn_connection_t *c2 = pn_connection(); pn_proactor_connect2(client, c2, NULL, listener_info(l2).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); TEST_PROACTORS_DRAIN(tps); /* Disconnect the client proactor */ pn_condition_t *cond = pn_condition(); pn_condition_set_name(cond, "test-name"); pn_condition_set_description(cond, "test-description"); pn_proactor_disconnect(client, cond); /* Verify expected client side first */ TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, test_proactors_run(&tps[0], 1)); TEST_COND_NAME(t, "test-name", last_condition); TEST_COND_DESC(t, "test-description", last_condition); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, test_proactors_run(&tps[0], 1)); TEST_COND_NAME(t, "test-name", last_condition); TEST_COND_DESC(t, "test-description", last_condition); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, test_proactors_run(&tps[0], 1)); /* Now check server sees the disconnects */ TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* Now disconnect the server end (the listeners) */ pn_proactor_disconnect(server, cond); pn_condition_free(cond); TEST_ETYPE_EQUAL(t, PN_LISTENER_CLOSE, TEST_PROACTORS_RUN(tps)); TEST_ETYPE_EQUAL(t, PN_LISTENER_CLOSE, TEST_PROACTORS_RUN(tps)); TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps)); /* Make sure the proactors are still functional */ pn_listener_t *l3 = test_listen(&tps[1], ""); pn_proactor_connect2(client, NULL, NULL, listener_info(l3).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); pn_proactor_disconnect(client, NULL); TEST_PROACTORS_DRAIN(tps); TEST_PROACTORS_DESTROY(tps); }
void qdr_error_copy(qdr_error_t *from, pn_condition_t *to) { if (from->name) { unsigned char *name = qd_field_iterator_copy(from->name->iterator); pn_condition_set_name(to, (char*) name); free(name); } if (from->description) { unsigned char *desc = qd_field_iterator_copy(from->description->iterator); pn_condition_set_description(to, (char*) desc); free(desc); } if (from->info) pn_data_copy(pn_condition_info(to), from->info); }
void pni_handle_bound(pn_reactor_t *reactor, pn_event_t *event) { assert(reactor); assert(event); pn_connection_t *conn = pn_event_connection(event); pn_transport_t *transport = pn_event_transport(event); pn_record_t *record = pn_connection_attachments(conn); pn_url_t *url = (pn_url_t *)pn_record_get(record, PNI_CONN_PEER_ADDRESS); const char *host = NULL; const char *port = "5672"; pn_string_t *str = NULL; // link the new transport to its reactor: pni_record_init_reactor(pn_transport_attachments(transport), reactor); if (pn_connection_acceptor(conn) != NULL) { // this connection was created by the acceptor. There is already a // socket assigned to this connection. Nothing needs to be done. return; } if (url) { host = pn_url_get_host(url); const char *uport = pn_url_get_port(url); if (uport) { port = uport; } else { const char *scheme = pn_url_get_scheme(url); if (scheme && strcmp(scheme, "amqps") == 0) { port = "5671"; } } if (!pn_connection_get_user(conn)) { // user did not manually set auth info const char *user = pn_url_get_username(url); if (user) pn_connection_set_user(conn, user); const char *passwd = pn_url_get_password(url); if (passwd) pn_connection_set_password(conn, passwd); } } else { // for backward compatibility, see if the connection's hostname can be // used for the remote address. See JIRA PROTON-1133 const char *hostname = pn_connection_get_hostname(conn); if (hostname) { str = pn_string(hostname); char *h = pn_string_buffer(str); // see if a port has been included in the hostname. This is not // allowed by the spec, but the old reactor interface allowed it. char *colon = strrchr(h, ':'); if (colon) { *colon = '\0'; port = colon + 1; } host = h; } } if (!host) { // error: no address configured pn_condition_t *cond = pn_transport_condition(transport); pn_condition_set_name(cond, "proton:io"); pn_condition_set_description(cond, "Connection failed: no address configured"); pn_transport_close_tail(transport); pn_transport_close_head(transport); } else { pn_socket_t sock = pn_connect(pni_reactor_io(reactor), host, port); // invalid sockets are ignored by poll, so we need to do this manually if (sock == PN_INVALID_SOCKET) { pn_condition_t *cond = pn_transport_condition(transport); pn_condition_set_name(cond, "proton:io"); pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor))); pn_transport_close_tail(transport); pn_transport_close_head(transport); } else { pn_reactor_selectable_transport(reactor, sock, transport); } } pn_free(str); }