void qd_connection_manager_delete_connector(qd_dispatch_t *qd, void *impl)
{
    qd_connector_t *ct = (qd_connector_t*) impl;
    if (ct) {
        sys_mutex_lock(ct->lock);
        if (ct->ctx && ct->ctx->pn_conn) {
            qd_connection_invoke_deferred(ct->ctx, deferred_close, ct->ctx->pn_conn);
        }
        sys_mutex_unlock(ct->lock);
        DEQ_REMOVE(qd->connection_manager->connectors, ct);
        qd_connector_decref(ct);
    }
}
Exemple #2
0
int pn_event_handler(void *handler_context, void *conn_context, pn_event_t *event, qd_connection_t *qd_conn)
{
    qd_container_t  *container = (qd_container_t*) handler_context;
    pn_connection_t *conn      = qd_connection_pn(qd_conn);
    pn_session_t    *ssn;
    pn_link_t       *pn_link;
    qd_link_t       *qd_link;
    pn_delivery_t   *delivery;

    switch (pn_event_type(event)) {
    case PN_CONNECTION_REMOTE_OPEN :
        qd_connection_set_user(qd_conn);
        if (pn_connection_state(conn) & PN_LOCAL_UNINIT) {
            // This Open is an externally initiated connection
            // Let policy engine decide
            qd_connection_set_event_stall(qd_conn, true);
            qd_conn->open_container = (void *)container;
            qd_connection_invoke_deferred(qd_conn, qd_policy_amqp_open, qd_conn);
        } else {
            // This Open is in response to an internally initiated connection
            notify_opened(container, qd_conn, conn_context);
        }
        break;

    case PN_CONNECTION_REMOTE_CLOSE :
        if (pn_connection_state(conn) == (PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED))
            pn_connection_close(conn);
        break;

    case PN_SESSION_REMOTE_OPEN :
        if (!(pn_connection_state(conn) & PN_LOCAL_CLOSED)) {
            ssn = pn_event_session(event);
            if (pn_session_state(ssn) & PN_LOCAL_UNINIT) {
                if (qd_conn->policy_settings) {
                    if (!qd_policy_approve_amqp_session(ssn, qd_conn)) {
                        break;
                    }
                    qd_conn->n_sessions++;
                }
                qd_policy_apply_session_settings(ssn, qd_conn);
                pn_session_open(ssn);
            }
        }
        break;

    case PN_SESSION_REMOTE_CLOSE :
        if (!(pn_connection_state(conn) & PN_LOCAL_CLOSED)) {
            ssn = pn_event_session(event);
            if (pn_session_state(ssn) == (PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED)) {
                // remote has nuked our session.  Check for any links that were
                // left open and forcibly detach them, since no detaches will
                // arrive on this session.
                pn_connection_t *conn = pn_session_connection(ssn);
                pn_link_t *pn_link = pn_link_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE);
                while (pn_link) {
                    if (pn_link_session(pn_link) == ssn) {
                        qd_link_t *qd_link = (qd_link_t*) pn_link_get_context(pn_link);
                        if (qd_link && qd_link->node) {
                            if (qd_conn->policy_settings) {
                                if (qd_link->direction == QD_OUTGOING) {
                                    qd_conn->n_receivers--;
                                    assert(qd_conn->n_receivers >= 0);
                                } else {
                                    qd_conn->n_senders--;
                                    assert(qd_conn->n_senders >= 0);
                                }
                            }
                            qd_log(container->log_source, QD_LOG_NOTICE,
                                   "Aborting link '%s' due to parent session end",
                                   pn_link_name(pn_link));
                            qd_link->node->ntype->link_detach_handler(qd_link->node->context,
                                                                      qd_link, QD_LOST);
                        }
                    }
                    pn_link = pn_link_next(pn_link, PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE);
                }
                if (qd_conn->policy_settings) {
                    qd_conn->n_sessions--;
                }
                pn_session_close(ssn);
            }
        }
        break;

    case PN_LINK_REMOTE_OPEN :
        if (!(pn_connection_state(conn) & PN_LOCAL_CLOSED)) {
            pn_link = pn_event_link(event);
            if (pn_link_state(pn_link) & PN_LOCAL_UNINIT) {
                if (pn_link_is_sender(pn_link)) {
                    if (qd_conn->policy_settings) {
                        if (!qd_policy_approve_amqp_receiver_link(pn_link, qd_conn)) {
                            break;
                        }
                        qd_conn->n_receivers++;
                    }
                    setup_outgoing_link(container, pn_link);
                } else {
                    if (qd_conn->policy_settings) {
                        if (!qd_policy_approve_amqp_sender_link(pn_link, qd_conn)) {
                            break;
                        }
                        qd_conn->n_senders++;
                    }
                    setup_incoming_link(container, pn_link);
                }
            } else if (pn_link_state(pn_link) & PN_LOCAL_ACTIVE)
                handle_link_open(container, pn_link);
        }
        break;

    case PN_LINK_REMOTE_CLOSE :
    case PN_LINK_REMOTE_DETACH :
        if (!(pn_connection_state(conn) & PN_LOCAL_CLOSED)) {
            pn_link = pn_event_link(event);
            qd_link = (qd_link_t*) pn_link_get_context(pn_link);
            if (qd_link) {
                qd_node_t *node = qd_link->node;
                qd_detach_type_t dt = pn_event_type(event) == PN_LINK_REMOTE_CLOSE ? QD_CLOSED : QD_DETACHED;
                if (node)
                    node->ntype->link_detach_handler(node->context, qd_link, dt);
                else if (qd_link->pn_link == pn_link) {
                    pn_link_close(pn_link);
                }
                if (qd_conn->policy_counted && qd_conn->policy_settings) {
                    if (pn_link_is_sender(pn_link)) {
                        qd_conn->n_receivers--;
                        qd_log(container->log_source, QD_LOG_TRACE,
                               "Closed receiver link %s. n_receivers: %d",
                               pn_link_name(pn_link), qd_conn->n_receivers);
                        assert (qd_conn->n_receivers >= 0);
                    } else {
                        qd_conn->n_senders--;
                        qd_log(container->log_source, QD_LOG_TRACE,
                               "Closed sender link %s. n_senders: %d",
                               pn_link_name(pn_link), qd_conn->n_senders);
                        assert (qd_conn->n_senders >= 0);
                    }
                }
                if (qd_link->close_sess_with_link && qd_link->pn_sess &&
                    pn_link_state(pn_link) == (PN_LOCAL_CLOSED | PN_REMOTE_CLOSED))
                    pn_session_close(qd_link->pn_sess);
            }
        }
        break;

    case PN_LINK_FLOW :
        pn_link = pn_event_link(event);
        qd_link = (qd_link_t*) pn_link_get_context(pn_link);
        if (qd_link && qd_link->node && qd_link->node->ntype->link_flow_handler)
            qd_link->node->ntype->link_flow_handler(qd_link->node->context, qd_link);
        break;

    case PN_DELIVERY :
        delivery = pn_event_delivery(event);
        if (pn_delivery_readable(delivery))
            do_receive(delivery);

        if (pn_delivery_updated(delivery)) {
            do_updated(delivery);
            pn_delivery_clear(delivery);
        }
        break;

    case PN_EVENT_NONE :
    case PN_REACTOR_INIT :
    case PN_REACTOR_QUIESCED :
    case PN_REACTOR_FINAL :
    case PN_TIMER_TASK :
    case PN_CONNECTION_INIT :
    case PN_CONNECTION_BOUND :
    case PN_CONNECTION_UNBOUND :
    case PN_CONNECTION_LOCAL_OPEN :
    case PN_CONNECTION_LOCAL_CLOSE :
    case PN_CONNECTION_FINAL :
    case PN_SESSION_INIT :
    case PN_SESSION_LOCAL_OPEN :
    case PN_SESSION_LOCAL_CLOSE :
    case PN_SESSION_FINAL :
    case PN_LINK_INIT :
    case PN_LINK_LOCAL_OPEN :
    case PN_LINK_LOCAL_CLOSE :
    case PN_LINK_LOCAL_DETACH :
    case PN_LINK_FINAL :
    case PN_TRANSPORT :
    case PN_TRANSPORT_ERROR :
    case PN_TRANSPORT_HEAD_CLOSED :
    case PN_TRANSPORT_TAIL_CLOSED :
    case PN_TRANSPORT_CLOSED :
    case PN_TRANSPORT_AUTHENTICATED :
    case PN_SELECTABLE_INIT :
    case PN_SELECTABLE_UPDATED :
    case PN_SELECTABLE_READABLE :
    case PN_SELECTABLE_WRITABLE :
    case PN_SELECTABLE_ERROR :
    case PN_SELECTABLE_EXPIRED :
    case PN_SELECTABLE_FINAL :
        break;
    }

    return 1;
}