static void pn_handshaker_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { switch (type) { case PN_CONNECTION_REMOTE_OPEN: { pn_connection_t *conn = pn_event_connection(event); if (pn_connection_state(conn) & PN_LOCAL_UNINIT) { pn_connection_open(conn); } } break; case PN_SESSION_REMOTE_OPEN: { pn_session_t *ssn = pn_event_session(event); if (pn_session_state(ssn) & PN_LOCAL_UNINIT) { pn_session_open(ssn); } } break; case PN_LINK_REMOTE_OPEN: { pn_link_t *link = pn_event_link(event); if (pn_link_state(link) & PN_LOCAL_UNINIT) { pn_terminus_copy(pn_link_source(link), pn_link_remote_source(link)); pn_terminus_copy(pn_link_target(link), pn_link_remote_target(link)); pn_link_open(link); } } break; case PN_CONNECTION_REMOTE_CLOSE: { pn_connection_t *conn = pn_event_connection(event); if (!(pn_connection_state(conn) & PN_LOCAL_CLOSED)) { pn_connection_close(conn); } } break; case PN_SESSION_REMOTE_CLOSE: { pn_session_t *ssn = pn_event_session(event); if (!(pn_session_state(ssn) & PN_LOCAL_CLOSED)) { pn_session_close(ssn); } } break; case PN_LINK_REMOTE_CLOSE: { pn_link_t *link = pn_event_link(event); if (!(pn_link_state(link) & PN_LOCAL_CLOSED)) { pn_link_close(link); } } break; default: break; } }
void messaging_adapter::on_link_remote_open(event &e) { proton_event *pe = dynamic_cast<proton_event*>(&e); if (pe) { messaging_event mevent(messaging_event::LINK_OPEN, *pe); on_link_open(mevent); pn_link_t *link = pn_event_link(pe->pn_event()); if (!is_local_open(pn_link_state(link)) && is_local_unititialised(pn_link_state(link))) { pn_link_open(link); } } }
void ConnectionContext::attach(pn_session_t* /*session*/, pn_link_t* link, int credit) { qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock); QPID_LOG(debug, "Attaching link " << link << ", state=" << pn_link_state(link)); pn_link_open(link); QPID_LOG(debug, "Link attached " << link << ", state=" << pn_link_state(link)); if (credit) pn_link_flow(link, credit); wakeupDriver(); while (pn_link_state(link) & PN_REMOTE_UNINIT) { QPID_LOG(debug, "waiting for confirmation of link attach for " << link << ", state=" << pn_link_state(link)); wait(); } }
void messaging_adapter::on_link_flow(proton_event &pe) { pn_event_t *pne = pe.pn_event(); pn_link_t *lnk = pn_event_link(pne); // TODO: process session flow data, if no link-specific data, just return. if (!lnk) return; link_context& lctx = link_context::get(lnk); int state = pn_link_state(lnk); if ((state&PN_LOCAL_ACTIVE) && (state&PN_REMOTE_ACTIVE)) { if (pn_link_is_sender(lnk)) { if (pn_link_credit(lnk) > 0) { sender s(make_wrapper<sender>(lnk)); if (pn_link_get_drain(lnk)) { if (!lctx.draining) { lctx.draining = true; delegate_.on_sender_drain_start(s); } } else { lctx.draining = false; } // create on_message extended event delegate_.on_sendable(s); } } else { // receiver if (!pn_link_credit(lnk) && lctx.draining) { lctx.draining = false; receiver r(make_wrapper<receiver>(lnk)); delegate_.on_receiver_drain_finish(r); } } } credit_topup(lnk); }
void messaging_adapter::on_delivery(event &e) { proton_event *pe = dynamic_cast<proton_event*>(&e); if (pe) { pn_event_t *cevent = pe->pn_event(); pn_link_t *lnk = pn_event_link(cevent); delivery dlv = pe->delivery(); if (pn_link_is_receiver(lnk)) { if (!dlv.partial() && dlv.readable()) { // generate on_message messaging_event mevent(messaging_event::MESSAGE, *pe); pn_connection_t *pnc = pn_session_connection(pn_link_session(lnk)); connection_context& ctx = connection_context::get(pnc); // Reusable per-connection message. // Avoid expensive heap malloc/free overhead. // See PROTON-998 class message &msg(ctx.event_message); mevent.message_ = &msg; mevent.message_->decode(lnk, dlv); if (pn_link_state(lnk) & PN_LOCAL_CLOSED) { if (auto_accept_) dlv.release(); } else { delegate_.on_message(mevent); if (auto_accept_ && !dlv.settled()) dlv.accept(); } } else if (dlv.updated() && dlv.settled()) { messaging_event mevent(messaging_event::DELIVERY_SETTLE, *pe); delegate_.on_delivery_settle(mevent); } } else { // sender if (dlv.updated()) { amqp_ulong rstate = dlv.remote_state(); if (rstate == PN_ACCEPTED) { messaging_event mevent(messaging_event::DELIVERY_ACCEPT, *pe); delegate_.on_delivery_accept(mevent); } else if (rstate == PN_REJECTED) { messaging_event mevent(messaging_event::DELIVERY_REJECT, *pe); delegate_.on_delivery_reject(mevent); } else if (rstate == PN_RELEASED || rstate == PN_MODIFIED) { messaging_event mevent(messaging_event::DELIVERY_RELEASE, *pe); delegate_.on_delivery_release(mevent); } if (dlv.settled()) { messaging_event mevent(messaging_event::DELIVERY_SETTLE, *pe); delegate_.on_delivery_settle(mevent); } if (auto_settle_) dlv.settle(); } } } }
void messaging_adapter::on_link_remote_open(proton_event &pe) { pn_link_t *lnk = pn_event_link(pe.pn_event()); container& c = pe.container(); if (pn_link_is_receiver(lnk)) { receiver r(make_wrapper<receiver>(lnk)); delegate_.on_receiver_open(r); if (is_local_unititialised(pn_link_state(lnk))) { r.open(c.receiver_options()); } } else { sender s(make_wrapper<sender>(lnk)); delegate_.on_sender_open(s); if (is_local_unititialised(pn_link_state(lnk))) { s.open(c.sender_options()); } } credit_topup(lnk); }
void messaging_adapter::on_link_local_open(event &e) { proton_event *pe = dynamic_cast<proton_event*>(&e); if (pe) { pn_link_t *link = pn_event_link(pe->pn_event()); if (is_remote_open(pn_link_state(link))) { messaging_event mevent(messaging_event::LINK_OPENED, *pe); on_link_opened(mevent); } } }
void qd_link_close(qd_link_t *link) { if (link->pn_link) pn_link_close(link->pn_link); if (link->close_sess_with_link && link->pn_sess && pn_link_state(link->pn_link) == (PN_LOCAL_CLOSED | PN_REMOTE_CLOSED)) { pn_session_close(link->pn_sess); } }
void messaging_adapter::on_link_remote_close(event &e) { proton_event *pe = dynamic_cast<proton_event*>(&e); if (pe) { pn_event_t *cevent = pe->pn_event(); pn_link_t *lnk = pn_event_link(cevent); pn_state_t state = pn_link_state(lnk); if (pn_condition_is_set(pn_link_remote_condition(lnk))) { messaging_event mevent(messaging_event::LINK_ERROR, *pe); on_link_error(mevent); } else if (is_local_closed(state)) { messaging_event mevent(messaging_event::LINK_CLOSED, *pe); on_link_closed(mevent); } else { messaging_event mevent(messaging_event::LINK_CLOSING, *pe); on_link_closing(mevent); } pn_link_close(lnk); } }
bool link::active() const { return ::active(pn_link_state(pn_object())); }
void messaging_adapter::on_delivery(proton_event &pe) { pn_event_t *cevent = pe.pn_event(); pn_link_t *lnk = pn_event_link(cevent); pn_delivery_t *dlv = pn_event_delivery(cevent); link_context& lctx = link_context::get(lnk); if (pn_link_is_receiver(lnk)) { delivery d(make_wrapper<delivery>(dlv)); if (!pn_delivery_partial(dlv) && pn_delivery_readable(dlv)) { // generate on_message pn_connection_t *pnc = pn_session_connection(pn_link_session(lnk)); connection_context& ctx = connection_context::get(pnc); // Reusable per-connection message. // Avoid expensive heap malloc/free overhead. // See PROTON-998 class message &msg(ctx.event_message); msg.decode(d); if (pn_link_state(lnk) & PN_LOCAL_CLOSED) { if (lctx.auto_accept) d.release(); } else { delegate_.on_message(d, msg); if (lctx.auto_accept && !d.settled()) d.accept(); if (lctx.draining && !pn_link_credit(lnk)) { lctx.draining = false; receiver r(make_wrapper<receiver>(lnk)); delegate_.on_receiver_drain_finish(r); } } } else if (pn_delivery_updated(dlv) && d.settled()) { delegate_.on_delivery_settle(d); } if (lctx.draining && pn_link_credit(lnk) == 0) { lctx.draining = false; pn_link_set_drain(lnk, false); receiver r(make_wrapper<receiver>(lnk)); delegate_.on_receiver_drain_finish(r); if (lctx.pending_credit) { pn_link_flow(lnk, lctx.pending_credit); lctx.pending_credit = 0; } } credit_topup(lnk); } else { tracker t(make_wrapper<tracker>(dlv)); // sender if (pn_delivery_updated(dlv)) { uint64_t rstate = pn_delivery_remote_state(dlv); if (rstate == PN_ACCEPTED) { delegate_.on_tracker_accept(t); } else if (rstate == PN_REJECTED) { delegate_.on_tracker_reject(t); } else if (rstate == PN_RELEASED || rstate == PN_MODIFIED) { delegate_.on_tracker_release(t); } if (t.settled()) { delegate_.on_tracker_settle(t); } if (lctx.auto_settle) t.settle(); } } }
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; }
endpoint::state link::state() const { return pn_link_state(pn_cast(this)); }
bool link::closed() const { return ::closed(pn_link_state(pn_object())); }
bool link::uninitialized() const { return ::uninitialized(pn_link_state(pn_object())); }
/* is the link ready to send messages? */ static sbool _is_ready(pn_link_t *link) { return (link && pn_link_state(link) == (PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE) && pn_link_credit(link) > 0); }
endpoint::state link::state() const { return pn_link_state(pn_object()); }