示例#1
0
/* Process each event emitted by the protocol engine */
static void dispatcher(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type)
{
	protocolState_t *ps = PROTOCOL_STATE(handler);
	const configSettings_t *cfg = ps->config;

	//DBGPRINTF("omamqp1: Event received: %s\n", pn_event_type_name(type));

	switch (type) {

	case PN_LINK_REMOTE_OPEN:
	    DBGPRINTF("omamqp1: Message bus opened link.\n");
	    break;

	case PN_DELIVERY:
	    // has the message been delivered to the message bus?
	    if (ps->delivery) {
	        assert(ps->delivery == pn_event_delivery(event));
	        if (pn_delivery_updated(ps->delivery)) {
	            rsRetVal result = RS_RET_IDLE;
	            uint64_t rs = pn_delivery_remote_state(ps->delivery);
	            switch (rs) {
	            case PN_ACCEPTED:
	                DBGPRINTF("omamqp1: Message ACCEPTED by message bus\n");
	                result = RS_RET_OK;
	                break;
	            case PN_REJECTED:
	              dbgprintf("omamqp1: message bus rejected log message: invalid message - dropping\n");
	                // message bus considers this a 'bad message'. Cannot be redelivered.
	                // Likely a configuration error. Drop the message by returning OK
	                result = RS_RET_OK;
	                break;
	            case PN_RELEASED:
	            case PN_MODIFIED:
		// the message bus cannot accept the message.  This may be temporary - retry
		// up to maxRetries before dropping
	                if (++ps->retries >= cfg->maxRetries) {
	                  dbgprintf("omamqp1: message bus failed to accept message - dropping\n");
	                  result = RS_RET_OK;
	                } else {
	                  dbgprintf("omamqp1: message bus cannot accept message, retrying\n");
	                  result = RS_RET_SUSPENDED;
	                }
	                break;
	            case PN_RECEIVED:
	                // not finished yet, wait for next delivery update
	                break;
	            default:
	                // no other terminal states defined, so ignore anything else
	                dbgprintf("omamqp1: unknown delivery state=0x%lX, assuming message accepted\n",
	                          (unsigned long) pn_delivery_remote_state(ps->delivery));
	                result = RS_RET_OK;
	                break;
	            }

	            if (result != RS_RET_IDLE) {
	                // the command is complete
	                threadIPC_t *ipc = ps->ipc;
	                pthread_mutex_lock(&ipc->lock);
	                assert(ipc->command == COMMAND_SEND);
	                ipc->result = result;
	                ipc->command = COMMAND_DONE;
	                pthread_cond_signal(&ipc->condition);
	                pthread_mutex_unlock(&ipc->lock);
	                pn_delivery_settle(ps->delivery);
	                ps->delivery = NULL;
	                if (result == RS_RET_OK) {
	                  ps->retries = 0;
	                }
	            }
	        }
	    }
	    break;


	case PN_CONNECTION_BOUND:
	    if (!cfg->bDisableSASL) {
	        // force use of SASL, even allowing PLAIN authentication
	        pn_sasl_t *sasl = pn_sasl(pn_event_transport(event));
#if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10
	        pn_sasl_set_allow_insecure_mechs(sasl, true);
#else
	        // proton version <= 0.9 only supports PLAIN authentication
	        const char *user = cfg->username
	            ? (char *)cfg->username
	            : pn_url_get_username(cfg->url);
	        if (user) {
	            pn_sasl_plain(sasl, user, (cfg->password
	                                       ? (char *) cfg->password
	                                       : pn_url_get_password(cfg->url)));
	        }
#endif
	    }
	    if (cfg->idleTimeout) {
	        // configured as seconds, set as milliseconds
	        pn_transport_set_idle_timeout(pn_event_transport(event),
	                                      cfg->idleTimeout * 1000);
	    }
	    break;

	case PN_CONNECTION_UNBOUND:
	    DBGPRINTF("omamqp1: cleaning up connection resources\n");
	    pn_connection_release(pn_event_connection(event));
	    ps->conn = NULL;
	    ps->sender = NULL;
	    ps->delivery = NULL;
	    break;


	case PN_TRANSPORT_ERROR:
	    {
	        // TODO: if auth failure, does it make sense to retry???
	        pn_transport_t *tport = pn_event_transport(event);
	        pn_condition_t *cond = pn_transport_condition(tport);
	        if (pn_condition_is_set(cond)) {
	            _log_error("transport failure", cond);
	        }
	        dbgprintf("omamqp1: network transport failed, reconnecting...\n");
	        // the protocol thread will attempt to reconnect if it is not
	        // being shut down
	    }
	    break;

	default:
	    break;
	}
}
示例#2
0
    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);
        }
    }