/* Test various SSL connections between proactors*/ static void test_ssl(test_t *t) { if (!pn_ssl_present()) { TEST_LOGF(t, "Skip SSL test, no support"); return; } test_proactor_t tps[] ={ test_proactor(t, ssl_client_handler), test_proactor(t, ssl_server_handler) }; test_proactor_t *client = &tps[0], *server = &tps[1]; pn_ssl_domain_t *cd = client->handler.ssl_domain = pn_ssl_domain(PN_SSL_MODE_CLIENT); pn_ssl_domain_t *sd = server->handler.ssl_domain = pn_ssl_domain(PN_SSL_MODE_SERVER); TEST_CHECK(t, 0 == SET_CREDENTIALS(sd, "tserver")); pn_listener_t *l = test_listen(server, ""); /* Basic SSL connection */ pn_proactor_connect2(client->proactor, NULL, NULL, listener_info(l).connect); /* Open ok at both ends */ TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); TEST_COND_EMPTY(t, last_condition); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); TEST_COND_EMPTY(t, last_condition); TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED); TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED); /* Verify peer with good hostname */ TEST_INT_EQUAL(t, 0, pn_ssl_domain_set_trusted_ca_db(cd, CERTIFICATE("tserver"))); TEST_INT_EQUAL(t, 0, pn_ssl_domain_set_peer_authentication(cd, PN_SSL_VERIFY_PEER_NAME, NULL)); pn_connection_t *c = pn_connection(); pn_connection_set_hostname(c, "test_server"); pn_proactor_connect2(client->proactor, c, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); TEST_COND_EMPTY(t, last_condition); TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps)); TEST_COND_EMPTY(t, last_condition); TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED); TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED); /* Verify peer with bad hostname */ c = pn_connection(); pn_connection_set_hostname(c, "wrongname"); pn_proactor_connect2(client->proactor, c, NULL, listener_info(l).connect); TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); TEST_COND_NAME(t, "amqp:connection:framing-error", last_condition); TEST_COND_DESC(t, "SSL", last_condition); TEST_PROACTORS_DRAIN(tps); pn_ssl_domain_free(cd); pn_ssl_domain_free(sd); TEST_PROACTORS_DESTROY(tps); }
void connector::connect() { pn_transport_t *pnt = pn_transport(); transport t(make_wrapper(pnt)); if (!address_.user().empty()) connection_.user(address_.user()); if (!address_.password().empty()) connection_.password(address_.password()); pn_transport_bind(pnt, unwrap(connection_)); pn_decref(pnt); // Apply options to the new transport. options_.apply(connection_); // if virtual-host not set, use host from address as default if (!options_.is_virtual_host_set()) pn_connection_set_hostname(unwrap(connection_), address_.host().c_str()); transport_configured_ = true; }
pn_connection_t *pn_messenger_domain(pn_messenger_t *messenger, const char *domain) { char buf[domain ? strlen(domain) + 1 : 1]; if (domain) { strcpy(buf, domain); } else { buf[0] = '\0'; } char *user = NULL; char *pass = NULL; char *host = "0.0.0.0"; char *port = "5672"; parse_url(buf, &user, &pass, &host, &port); for (int i = 0; i < messenger->size; i++) { pn_connection_t *connection = pn_connector_connection(messenger->connectors[i]); const char *container = pn_connection_remote_container(connection); const char *hostname = pn_connection_hostname(connection); if (pn_streq(container, domain) || pn_streq(hostname, domain)) return connection; } pn_connector_t *connector = pn_connector(messenger->driver, host, port, NULL); if (!connector) return NULL; messenger->connectors[messenger->size++] = connector; pn_sasl_t *sasl = pn_connector_sasl(connector); if (user) { pn_sasl_plain(sasl, user, pass); } else { pn_sasl_mechanisms(sasl, "ANONYMOUS"); pn_sasl_client(sasl); } pn_connection_t *connection = pn_connection(); pn_connection_set_container(connection, messenger->name); pn_connection_set_hostname(connection, domain); pn_connection_open(connection); pn_connector_set_connection(connector, connection); return connection; }
/* runs the protocol engine, allowing it to handle TCP socket I/O and timer * events in the background. */ static void *amqp1_thread(void *arg) { DBGPRINTF("omamqp1: Protocol thread started\n"); pn_handler_t *handler = (pn_handler_t *)arg; protocolState_t *ps = PROTOCOL_STATE(handler); const configSettings_t *cfg = ps->config; // have pn_reactor_process() exit after 5 sec to poll for commands pn_reactor_set_timeout(ps->reactor, 5000); pn_reactor_start(ps->reactor); while (!ps->stopped) { // setup a connection: const char *host = pn_url_get_host(cfg->url); const char *port = pn_url_get_port(cfg->url); if (!port) port = "5672"; #if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 13 ps->conn = pn_reactor_connection_to_host(ps->reactor, host, port, handler); pn_connection_set_hostname(ps->conn, host); #else { char host_addr[300]; ps->conn = pn_reactor_connection(ps->reactor, handler); snprintf(host_addr, sizeof(host_addr), "%s:%s", host, port); pn_connection_set_hostname(ps->conn, host_addr); } #endif pn_connection_set_container(ps->conn, "rsyslogd-omamqp1"); #if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10 // proton version <= 0.9 did not support Cyrus SASL const char *user = cfg->username ? (char *)cfg->username : pn_url_get_username(cfg->url); if (user) pn_connection_set_user(ps->conn, user); const char *pword = cfg->password ? (char *) cfg->password : pn_url_get_password(cfg->url); if (pword) pn_connection_set_password(ps->conn, pword); #endif pn_connection_open(ps->conn); pn_session_t *ssn = pn_session(ps->conn); pn_session_open(ssn); ps->sender = pn_sender(ssn, (char *)cfg->target); pn_link_set_snd_settle_mode(ps->sender, PN_SND_UNSETTLED); char *addr = (char *)ps->config->target; pn_terminus_set_address(pn_link_target(ps->sender), addr); pn_terminus_set_address(pn_link_source(ps->sender), addr); pn_link_open(ps->sender); // run the protocol engine until the connection closes or thread is shut down sbool engine_running = true; while (engine_running) { engine_running = pn_reactor_process(ps->reactor); _poll_command(ps); } DBGPRINTF("omamqp1: reactor finished\n"); _abort_command(ps); // unblock main thread if necessary // delay reconnectDelay seconds before re-connecting: int delay = ps->config->reconnectDelay; while (delay-- > 0 && !ps->stopped) { srSleep(1, 0); _poll_command(ps); } } pn_reactor_stop(ps->reactor); // stop command is now done: threadIPC_t *ipc = ps->ipc; pthread_mutex_lock(&ipc->lock); ipc->result = RS_RET_OK; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); pthread_mutex_unlock(&ipc->lock); DBGPRINTF("omamqp1: Protocol thread stopped\n"); return 0; }
void client_callback(pn_connector_t *ctor) { struct client_context *ctx = pn_connector_context(ctor); if (pn_connector_closed(ctor)) { ctx->done = true; } pn_sasl_t *sasl = pn_connector_sasl(ctor); while (pn_sasl_state(sasl) != PN_SASL_PASS) { pn_sasl_state_t st = pn_sasl_state(sasl); switch (st) { case PN_SASL_IDLE: return; case PN_SASL_CONF: if (ctx->mechanism && !strcmp(ctx->mechanism, "PLAIN")) { pn_sasl_plain(sasl, ctx->username, ctx->password); } else { pn_sasl_mechanisms(sasl, ctx->mechanism); pn_sasl_client(sasl); } break; case PN_SASL_STEP: if (pn_sasl_pending(sasl)) { fprintf(stderr, "challenge failed\n"); ctx->done = true; } return; case PN_SASL_FAIL: fprintf(stderr, "authentication failed\n"); ctx->done = true; return; case PN_SASL_PASS: break; } } pn_connection_t *connection = pn_connector_connection(ctor); char tagstr[1024]; char msg[ctx->size]; char data[ctx->size + 16]; for (int i = 0; i < ctx->size; i++) { msg[i] = 'x'; } size_t ndata = pn_message_data(data, ctx->size + 16, msg, ctx->size); if (!ctx->init) { ctx->init = true; char container[1024]; if (gethostname(container, 1024)) pn_fatal("hostname lookup failed"); pn_connection_set_container(connection, container); pn_connection_set_hostname(connection, ctx->hostname); pn_session_t *ssn = pn_session(connection); pn_connection_open(connection); pn_session_open(ssn); if (ctx->send_count) { pn_link_t *snd = pn_sender(ssn, "sender"); pn_set_target(snd, ctx->address); pn_link_open(snd); char buf[16]; for (int i = 0; i < ctx->send_count; i++) { sprintf(buf, "%x", i); pn_delivery(snd, pn_dtag(buf, strlen(buf))); } } if (ctx->recv_count) { pn_link_t *rcv = pn_receiver(ssn, "receiver"); pn_set_source(rcv, ctx->address); pn_link_open(rcv); pn_flow(rcv, ctx->recv_count < ctx->high ? ctx->recv_count : ctx->high); } } pn_delivery_t *delivery = pn_work_head(connection); while (delivery) { pn_delivery_tag_t tag = pn_delivery_tag(delivery); pn_quote_data(tagstr, 1024, tag.bytes, tag.size); pn_link_t *link = pn_link(delivery); if (pn_writable(delivery)) { pn_send(link, data, ndata); if (pn_advance(link)) { if (!ctx->quiet) printf("sent delivery: %s\n", tagstr); } } else if (pn_readable(delivery)) { if (!ctx->quiet) { printf("received delivery: %s\n", tagstr); printf(" payload = \""); } while (true) { size_t n = pn_recv(link, msg, 1024); if (n == PN_EOS) { pn_advance(link); pn_disposition(delivery, PN_ACCEPTED); pn_settle(delivery); if (!--ctx->recv_count) { pn_link_close(link); } break; } else if (!ctx->quiet) { pn_print_data(msg, n); } } if (!ctx->quiet) printf("\"\n"); if (pn_credit(link) < ctx->low && pn_credit(link) < ctx->recv_count) { pn_flow(link, (ctx->recv_count < ctx->high ? ctx->recv_count : ctx->high) - pn_credit(link)); } } if (pn_updated(delivery)) { if (!ctx->quiet) printf("disposition for %s: %u\n", tagstr, pn_remote_disposition(delivery)); pn_clear(delivery); pn_settle(delivery); if (!--ctx->send_count) { pn_link_close(link); } } delivery = pn_work_next(delivery); } if (!ctx->send_count && !ctx->recv_count) { printf("closing\n"); // XXX: how do we close the session? //pn_close((pn_endpoint_t *) ssn); pn_connection_close(connection); } if (pn_connection_state(connection) == (PN_LOCAL_CLOSED | PN_REMOTE_CLOSED)) { ctx->done = true; } }
void sender_dispatch(pn_handler_t *h, pn_event_t *event, pn_event_type_t type) { sender_context_t *sc = sender_context(h); switch (type) { case PN_CONNECTION_INIT: { pn_connection_t *conn = pn_event_connection(event); pn_connection_set_container(conn, pn_string_get(sc->container_id)); pn_connection_set_hostname(conn, pn_string_get(sc->hostname)); pn_connection_open(conn); pn_session_t *ssn = pn_session(conn); pn_session_open(ssn); pn_link_t *snd = pn_sender(ssn, "sender"); const char *path = pn_url_get_path(sc->send_url); if (path && strlen(path)) { pn_terminus_set_address(pn_link_target(snd), path); pn_terminus_set_address(pn_link_source(snd), path); } pn_link_open(snd); } break; case PN_LINK_FLOW: { pn_link_t *snd = pn_event_link(event); while (pn_link_credit(snd) > 0 && sc->sent < sc->opts->msg_count) { if (sc->sent == 0) statistics_start(sc->stats); char tag[8]; void *ptr = &tag; *((uint64_t *) ptr) = sc->sent; pn_delivery_t *dlv = pn_delivery(snd, pn_dtag(tag, 8)); // setup the message to send pn_message_t *msg = sc->message; pn_message_set_address(msg, sc->opts->targets.addresses[0]); sc->id.u.as_ulong = sc->sent; pn_message_set_correlation_id(msg, sc->id); pn_message_set_creation_time(msg, msgr_now()); size_t size = sc->encoded_data_size; int err = pn_message_encode(msg, sc->encoded_data, &size); check(err == 0, "message encoding error"); pn_link_send(snd, sc->encoded_data, size); pn_delivery_settle(dlv); sc->sent++; } if (sc->sent == sc->opts->msg_count && !sc->opts->get_replies) { pn_link_close(snd); pn_connection_t *conn = pn_event_connection(event); pn_connection_close(conn); } } break; case PN_LINK_INIT: { pn_link_t *link = pn_event_link(event); if (pn_link_is_receiver(link)) { // Response messages link. Could manage credit and deliveries in this handler but // a dedicated handler also works. pn_handler_t *replyto = replyto_handler(sc); pn_flowcontroller_t *fc = pn_flowcontroller(1024); pn_handler_add(replyto, fc); pn_decref(fc); pn_handshaker_t *handshaker = pn_handshaker(); pn_handler_add(replyto, handshaker); pn_decref(handshaker); pn_record_t *record = pn_link_attachments(link); pn_record_set_handler(record, replyto); pn_decref(replyto); } } break; case PN_CONNECTION_LOCAL_CLOSE: { statistics_report(sc->stats, sc->sent, sc->received); } break; default: break; } }