void process_flow(ldp_connection_t *conn, pn_event_t *event) { fprintf(stderr, "flow event %s\n", pn_event_type_name(pn_event_type(event))); pn_link_t *sender = pn_event_link(event); pn_message_t *message = pn_message(); pn_message_set_address(message, "amqp://foo/bar"); pn_data_t *body = pn_message_body(message); char *msgtext = "hello world!"; pn_data_put_string(body, pn_bytes(strlen(msgtext), msgtext)); pn_buffer_t *buffer = pn_buffer(1000); char *encoded = pn_buffer_bytes(buffer).start; size_t size = pn_buffer_capacity(buffer); int err = pn_message_encode(message, encoded, &size); if (err) { fprintf(stderr, "trouble encoding message\n"); } else { char tag[8]; static uint64_t next_tag; *((uint64_t*)tag) = ++next_tag; pn_delivery_t *d = pn_delivery(sender, pn_dtag(tag, 8)); pn_link_send(sender, encoded, size); pn_link_advance(sender); } pn_buffer_free(buffer); pn_message_free(message); }
bool ConnectionContext::get(boost::shared_ptr<SessionContext> ssn, boost::shared_ptr<ReceiverContext> lnk, qpid::messaging::Message& message, qpid::messaging::Duration timeout) { qpid::sys::AbsTime until(convert(timeout)); while (true) { qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock); pn_delivery_t* current = pn_link_current((pn_link_t*) lnk->receiver); QPID_LOG(debug, "In ConnectionContext::get(), current=" << current); if (current) { qpid::messaging::MessageImpl& impl = MessageImplAccess::get(message); boost::shared_ptr<EncodedMessage> encoded(new EncodedMessage(pn_delivery_pending(current))); ssize_t read = pn_link_recv(lnk->receiver, encoded->getData(), encoded->getSize()); if (read < 0) throw qpid::messaging::MessagingException("Failed to read message"); encoded->trim((size_t) read); QPID_LOG(debug, "Received message of " << encoded->getSize() << " bytes: "); encoded->init(impl); impl.setEncoded(encoded); impl.setInternalId(ssn->record(current)); pn_link_advance(lnk->receiver); return true; } else if (until > qpid::sys::now()) { wait(); } else { return false; } } return false; }
void SenderContext::Delivery::send(pn_link_t* sender) { pn_delivery_tag_t tag; tag.size = sizeof(id); tag.bytes = reinterpret_cast<const char*>(&id); token = pn_delivery(sender, tag); pn_link_send(sender, encoded.getData(), encoded.getSize()); pn_link_advance(sender); }
static pn_event_type_t message_stream_handler(test_handler_t *th, pn_event_t *e) { struct message_stream_context *ctx = (struct message_stream_context*)th->context; switch (pn_event_type(e)) { case PN_CONNECTION_BOUND: pn_transport_set_max_frame(pn_event_transport(e), FRAME); return PN_EVENT_NONE; case PN_SESSION_INIT: pn_session_set_incoming_capacity(pn_event_session(e), FRAME); /* Single frame incoming */ pn_session_set_outgoing_window(pn_event_session(e), 1); /* Single frame outgoing */ return PN_EVENT_NONE; case PN_LINK_REMOTE_OPEN: common_handler(th, e); if (pn_link_is_receiver(pn_event_link(e))) { pn_link_flow(pn_event_link(e), 1); } else { ctx->sender = pn_event_link(e); } return PN_EVENT_NONE; case PN_LINK_FLOW: /* Start a delivery */ if (pn_link_is_sender(pn_event_link(e)) && !ctx->dlv) { ctx->dlv = pn_delivery(pn_event_link(e), pn_dtag("x", 1)); } return PN_LINK_FLOW; case PN_CONNECTION_WAKE: { /* Send a chunk */ ssize_t remains = ctx->size - ctx->sent; ssize_t n = (CHUNK < remains) ? CHUNK : remains; TEST_CHECK(th->t, n == pn_link_send(ctx->sender, ctx->send_buf.start + ctx->sent, n)); ctx->sent += n; if (ctx->sent == ctx->size) { TEST_CHECK(th->t, pn_link_advance(ctx->sender)); } return PN_CONNECTION_WAKE; } case PN_DELIVERY: { /* Receive a delivery - smaller than a chunk? */ pn_delivery_t *dlv = pn_event_delivery(e); if (pn_delivery_readable(dlv)) { ssize_t n = pn_delivery_pending(dlv); rwbytes_ensure(&ctx->recv_buf, ctx->received + n); TEST_ASSERT(n == pn_link_recv(pn_event_link(e), ctx->recv_buf.start + ctx->received, n)); ctx->received += n; } ctx->complete = !pn_delivery_partial(dlv); return PN_DELIVERY; } default: return common_handler(th, e); } }
void DecodingIncoming::readable(pn_delivery_t* delivery) { boost::intrusive_ptr<Message> received(new Message(pn_delivery_pending(delivery))); /*ssize_t read = */pn_link_recv(link, received->getData(), received->getSize()); received->scan(); pn_link_advance(link); qpid::broker::Message message(received, received); handle(message); --window; received->begin(); Transfer t(delivery, session); received->end(t); }
tracker sender::send(const message &message) { uint64_t id = ++tag_counter; pn_delivery_t *dlv = pn_delivery(pn_object(), pn_dtag(reinterpret_cast<const char*>(&id), sizeof(id))); std::vector<char> buf; message.encode(buf); assert(!buf.empty()); pn_link_send(pn_object(), &buf[0], buf.size()); pn_link_advance(pn_object()); if (pn_link_snd_settle_mode(pn_object()) == PN_SND_SETTLED) pn_delivery_settle(dlv); if (!pn_link_credit(pn_object())) link_context::get(pn_object()).draining = false; return make_wrapper<tracker>(dlv); }
static void CORE_link_deliver(void *context, qdr_link_t *link, qdr_delivery_t *dlv, bool settled) { qd_router_t *router = (qd_router_t*) context; qd_link_t *qlink = (qd_link_t*) qdr_link_get_context(link); if (!qlink) return; pn_link_t *plink = qd_link_pn(qlink); if (!plink) return; const char *tag; int tag_length; qdr_delivery_tag(dlv, &tag, &tag_length); pn_delivery(plink, pn_dtag(tag, tag_length)); pn_delivery_t *pdlv = pn_link_current(plink); // // If the remote send settle mode is set to 'settled', we should settle the delivery on behalf of the receiver. // bool remote_snd_settled = qd_link_remote_snd_settle_mode(qlink) == PN_SND_SETTLED; if (!settled && !remote_snd_settled) { pn_delivery_set_context(pdlv, dlv); qdr_delivery_set_context(dlv, pdlv); qdr_delivery_incref(dlv); } qd_message_send(qdr_delivery_message(dlv), qlink, qdr_link_strip_annotations_out(link)); if (!settled && remote_snd_settled) // Tell the core that the delivery has been accepted and settled, since we are settling on behalf of the receiver qdr_delivery_update_disposition(router->router_core, dlv, PN_ACCEPTED, true, false); if (settled || remote_snd_settled) pn_delivery_settle(pdlv); pn_link_advance(plink); }
void BufferedTransfer::initIn(pn_link_t* link, pn_delivery_t* d) { in.handle = d; //read in data data.resize(pn_delivery_pending(d)); /*ssize_t read = */pn_link_recv(link, &data[0], data.size()); pn_link_advance(link); //copy delivery tag pn_delivery_tag_t dt = pn_delivery_tag(d); tag.resize(dt.size); #ifdef NO_PROTON_DELIVERY_TAG_T ::memmove(&tag[0], dt.start, dt.size); #else ::memmove(&tag[0], dt.bytes, dt.size); #endif //set context pn_delivery_set_context(d, this); }
static void do_receive(pn_delivery_t *pnd) { pn_link_t *pn_link = pn_delivery_link(pnd); qd_link_t *link = (qd_link_t*) pn_link_get_context(pn_link); if (link) { qd_node_t *node = link->node; if (node) { node->ntype->rx_handler(node->context, link, pnd); return; } } // // Reject the delivery if we couldn't find a node to handle it // pn_link_advance(pn_link); pn_link_flow(pn_link, 1); pn_delivery_update(pnd, PN_REJECTED); pn_delivery_settle(pnd); }
/** * Outbound Delivery Handler */ static void router_tx_handler(void* context, dx_link_t *link, pn_delivery_t *delivery) { dx_router_t *router = (dx_router_t*) context; pn_link_t *pn_link = pn_delivery_link(delivery); dx_router_link_t *rlink = (dx_router_link_t*) dx_link_get_context(link); dx_message_t *msg; size_t size; sys_mutex_lock(router->lock); msg = DEQ_HEAD(rlink->out_fifo); if (!msg) { // TODO - Recind the delivery sys_mutex_unlock(router->lock); return; } DEQ_REMOVE_HEAD(rlink->out_fifo); size = (DEQ_SIZE(rlink->out_fifo)); sys_mutex_unlock(router->lock); dx_message_send(msg, pn_link); // // If there is no incoming delivery, it was pre-settled. In this case, // we must pre-settle the outgoing delivery as well. // if (dx_message_in_delivery(msg)) { pn_delivery_set_context(delivery, (void*) msg); dx_message_set_out_delivery(msg, delivery); } else { pn_delivery_settle(delivery); dx_free_message(msg); } pn_link_advance(pn_link); pn_link_offered(pn_link, size); }
bool link::advance() { return pn_link_advance(pn_object()); }
/** * Inbound Delivery Handler */ static void AMQP_rx_handler(void* context, qd_link_t *link, pn_delivery_t *pnd) { qd_router_t *router = (qd_router_t*) context; pn_link_t *pn_link = qd_link_pn(link); qdr_link_t *rlink = (qdr_link_t*) qd_link_get_context(link); qdr_delivery_t *delivery = 0; qd_message_t *msg; // // Receive the message into a local representation. If the returned message // pointer is NULL, we have not yet received a complete message. // // Note: In the link-routing case, consider cutting the message through. There's // no reason to wait for the whole message to be received before starting to // send it. // msg = qd_message_receive(pnd); if (!msg) return; // // Consume the delivery. // pn_link_advance(pn_link); // // If there's no router link, free the message and finish. It's likely that the link // is closing. // if (!rlink) { qd_message_free(msg); return; } // // Handle the link-routed case // if (qdr_link_is_routed(rlink)) { pn_delivery_tag_t dtag = pn_delivery_tag(pnd); delivery = qdr_link_deliver_to_routed_link(rlink, msg, pn_delivery_settled(pnd), (uint8_t*) dtag.start, dtag.size); if (delivery) { if (pn_delivery_settled(pnd)) pn_delivery_settle(pnd); else { pn_delivery_set_context(pnd, delivery); qdr_delivery_set_context(delivery, pnd); qdr_delivery_incref(delivery); } } return; } // // Determine if the incoming link is anonymous. If the link is addressed, // there are some optimizations we can take advantage of. // bool anonymous_link = qdr_link_is_anonymous(rlink); // // Determine if the user of this connection is allowed to proxy the // user_id of messages. A message user_id is proxied when the // property value differs from the authenticated user name of the connection. // If the user is not allowed to proxy the user_id then the message user_id // must be blank or it must be equal to the connection user name. // bool check_user = false; qd_connection_t *conn = qd_link_connection(link); if (conn->policy_settings) check_user = !conn->policy_settings->allowUserIdProxy; // // Validate the content of the delivery as an AMQP message. This is done partially, only // to validate that we can find the fields we need to route the message. // // If the link is anonymous, we must validate through the message properties to find the // 'to' field. If the link is not anonymous, we don't need the 'to' field as we will be // using the address from the link target. // qd_message_depth_t validation_depth = (anonymous_link || check_user) ? QD_DEPTH_PROPERTIES : QD_DEPTH_MESSAGE_ANNOTATIONS; bool valid_message = qd_message_check(msg, validation_depth); if (valid_message) { if (check_user) { // This connection must not allow proxied user_id qd_iterator_t *userid_iter = qd_message_field_iterator(msg, QD_FIELD_USER_ID); if (userid_iter) { // The user_id property has been specified if (qd_iterator_remaining(userid_iter) > 0) { // user_id property in message is not blank if (!qd_iterator_equal(userid_iter, (const unsigned char *)conn->user_id)) { // This message is rejected: attempted user proxy is disallowed qd_log(router->log_source, QD_LOG_DEBUG, "Message rejected due to user_id proxy violation. User:%s", conn->user_id); pn_link_flow(pn_link, 1); pn_delivery_update(pnd, PN_REJECTED); pn_delivery_settle(pnd); qd_message_free(msg); qd_iterator_free(userid_iter); return; } } qd_iterator_free(userid_iter); } } qd_parsed_field_t *in_ma = qd_message_message_annotations(msg); qd_bitmask_t *link_exclusions; bool strip = qdr_link_strip_annotations_in(rlink); qd_iterator_t *ingress_iter = router_annotate_message(router, in_ma, msg, &link_exclusions, strip); if (anonymous_link) { qd_iterator_t *addr_iter = 0; int phase = 0; // // If the message has delivery annotations, get the to-override field from the annotations. // if (in_ma) { qd_parsed_field_t *ma_to = qd_parse_value_by_key(in_ma, QD_MA_TO); if (ma_to) { addr_iter = qd_iterator_dup(qd_parse_raw(ma_to)); phase = qd_message_get_phase_annotation(msg); } } // // Still no destination address? Use the TO field from the message properties. // if (!addr_iter) addr_iter = qd_message_field_iterator(msg, QD_FIELD_TO); if (addr_iter) { qd_iterator_reset_view(addr_iter, ITER_VIEW_ADDRESS_HASH); if (phase > 0) qd_iterator_annotate_phase(addr_iter, '0' + (char) phase); delivery = qdr_link_deliver_to(rlink, msg, ingress_iter, addr_iter, pn_delivery_settled(pnd), link_exclusions); } } else { const char *term_addr = pn_terminus_get_address(qd_link_remote_target(link)); if (!term_addr) term_addr = pn_terminus_get_address(qd_link_source(link)); if (term_addr) { qd_composed_field_t *to_override = qd_compose_subfield(0); qd_compose_insert_string(to_override, term_addr); qd_message_set_to_override_annotation(msg, to_override); int phase = qdr_link_phase(rlink); if (phase != 0) qd_message_set_phase_annotation(msg, phase); } delivery = qdr_link_deliver(rlink, msg, ingress_iter, pn_delivery_settled(pnd), link_exclusions); } if (delivery) { if (pn_delivery_settled(pnd)) pn_delivery_settle(pnd); else { pn_delivery_set_context(pnd, delivery); qdr_delivery_set_context(delivery, pnd); qdr_delivery_incref(delivery); } } else { // // The message is now and will always be unroutable because there is no address. // pn_link_flow(pn_link, 1); pn_delivery_update(pnd, PN_REJECTED); pn_delivery_settle(pnd); qd_message_free(msg); } // // Rules for delivering messages: // // For addressed (non-anonymous) links: // to-override must be set (done in the core?) // uses qdr_link_deliver to hand over to the core // // For anonymous links: // If there's a to-override in the annotations, use that address // Or, use the 'to' field in the message properties // } else { // // Message is invalid. Reject the message and don't involve the router core. // pn_link_flow(pn_link, 1); pn_delivery_update(pnd, PN_REJECTED); pn_delivery_settle(pnd); qd_message_free(msg); } }
// check if a command needs processing static void _poll_command(protocolState_t *ps) { if (ps->stopped) return; threadIPC_t *ipc = ps->ipc; pthread_mutex_lock(&ipc->lock); switch (ipc->command) { case COMMAND_SHUTDOWN: DBGPRINTF("omamqp1: Protocol thread processing shutdown command\n"); ps->stopped = true; _close_connection(ps); // wait for the shutdown to complete before ack'ing this command break; case COMMAND_IS_READY: DBGPRINTF("omamqp1: Protocol thread processing ready query command\n"); ipc->result = _is_ready(ps->sender) ? RS_RET_OK : RS_RET_SUSPENDED; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); break; case COMMAND_SEND: if (ps->delivery) break; // currently processing this command DBGPRINTF("omamqp1: Protocol thread processing send message command\n"); if (!_is_ready(ps->sender)) { ipc->result = RS_RET_SUSPENDED; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); break; } // send the message ++ps->tag; ps->delivery = pn_delivery(ps->sender, pn_dtag((const char *)&ps->tag, sizeof(ps->tag))); pn_message_t *message = ipc->message; assert(message); int rc = 0; size_t len = ps->buffer_size; do { rc = pn_message_encode(message, ps->encode_buffer, &len); if (rc == PN_OVERFLOW) { _grow_buffer(ps); len = ps->buffer_size; } } while (rc == PN_OVERFLOW); pn_link_send(ps->sender, ps->encode_buffer, len); pn_link_advance(ps->sender); ++ps->msgs_sent; // command completes when remote updates the delivery (see PN_DELIVERY) break; case COMMAND_DONE: break; } pthread_mutex_unlock(&ipc->lock); }
int main ( int argc, char ** argv ) { char info[1000]; int expected = (argc > 1) ? atoi(argv[1]) : 100000; int received = 0; int size = 32; int msg_size = 50; bool done = false; int initial_credit = 500, new_credit = 250, low_credit_limit = 250; char const * host = "0.0.0.0"; char const * port = "5672"; bool sasl_done = false; pn_driver_t * driver; pn_listener_t * listener; pn_connector_t * connector; pn_connection_t * connection; pn_session_t * session; pn_link_t * link; pn_delivery_t * delivery; char * message_data = (char *) malloc ( MY_BUF_SIZE ); int message_data_capacity = MY_BUF_SIZE; fprintf ( stderr, "drecv expecting %d messages.\n", expected ); driver = pn_driver ( ); if ( ! pn_listener(driver, host, port, 0) ) { fprintf ( stderr, "listener creation failed.\n" ); exit ( 1 ); } while ( ! done) { pn_driver_wait ( driver, -1 ); if ( (listener = pn_driver_listener(driver)) ) pn_listener_accept( listener ); if ( (connector = pn_driver_connector(driver)) ) { pn_connector_process ( connector ); if ( ! sasl_done ) if( ! (sasl_done = get_sasl_over_with(connector) )) continue; connection = pn_connector_connection ( connector ); /*========================================================= Open everything that is ready on the other side but not here. =========================================================*/ pn_state_t hes_ready_im_not = PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE; if (pn_connection_state(connection) == hes_ready_im_not) pn_connection_open( connection); for ( session = pn_session_head(connection, hes_ready_im_not); session; session = pn_session_next(session, hes_ready_im_not) ) pn_session_open(session); for ( link = pn_link_head(connection, hes_ready_im_not); link; link = pn_link_next(link, hes_ready_im_not) ) { 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 ); if ( pn_link_is_receiver(link) ) pn_link_flow ( link, initial_credit ); } /*========================================================== Get all available deliveries. ==========================================================*/ for ( delivery = pn_work_head ( connection ); delivery; delivery = pn_work_next ( delivery ) ) { if ( pn_delivery_readable(delivery) ) { link = pn_delivery_link ( delivery ); while ( PN_EOS != pn_link_recv(link, message_data, MY_BUF_SIZE) ) ; pn_link_advance ( link ); pn_delivery_update ( delivery, PN_ACCEPTED ); pn_delivery_settle ( delivery ); if ( ++ received >= expected ) { sprintf ( info, "received %d messages", received ); print_timestamp ( stderr, info ); done = true; } // a progress report for long tests. if ( ! (received % 5000000) ) fprintf ( stderr, "received: %d\n", received ); if ( pn_link_credit(link) <= low_credit_limit ) pn_link_flow ( link, new_credit ); } else { // TODO // Why am I getting writables? // And what to do with them? } } /*=============================================================== Shut down everything that the other side has closed. ===============================================================*/ pn_state_t active_here_closed_there = PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED; if ( pn_connection_state(connection) == active_here_closed_there ) pn_connection_close ( connection ); for ( session = pn_session_head(connection, active_here_closed_there); session; session = pn_session_next(session, active_here_closed_there) ) pn_session_close ( session ); for ( link = pn_link_head(connection, active_here_closed_there); link; link = pn_link_next(link, active_here_closed_there) ) pn_link_close ( link ); if ( pn_connector_closed(connector) ) { pn_connection_free ( pn_connector_connection(connector) ); pn_connector_free ( connector ); done = true; } else pn_connector_process(connector); } } pn_driver_free(driver); return 0; }
/* Process each event posted by the reactor. */ static void event_handler(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { app_data_t *data = GET_APP_DATA(handler); switch (type) { case PN_CONNECTION_INIT: { // Create and open all the endpoints needed to send a message // pn_connection_t *conn; pn_session_t *ssn; pn_link_t *sender; conn = pn_event_connection(event); pn_connection_open(conn); ssn = pn_session(conn); pn_session_open(ssn); sender = pn_sender(ssn, "MySender"); // we do not wait for ack until the last message pn_link_set_snd_settle_mode(sender, PN_SND_MIXED); if (!data->anon) { pn_terminus_set_address(pn_link_target(sender), data->target); } pn_link_open(sender); } break; case PN_LINK_FLOW: { // the remote has given us some credit, now we can send messages // static long tag = 0; // a simple tag generator pn_delivery_t *delivery; pn_link_t *sender = pn_event_link(event); int credit = pn_link_credit(sender); while (credit > 0 && data->count > 0) { --credit; --data->count; ++tag; delivery = pn_delivery(sender, pn_dtag((const char *)&tag, sizeof(tag))); pn_link_send(sender, data->msg_data, data->msg_len); pn_link_advance(sender); if (data->count > 0) { // send pre-settled until the last one, then wait for an ack on // the last sent message. This allows the sender to send // messages as fast as possible and then exit when the consumer // has dealt with the last one. // pn_delivery_settle(delivery); } } } break; case PN_DELIVERY: { // Since the example sends all messages but the last pre-settled // (pre-acked), only the last message's delivery will get updated with // the remote state (acked/nacked). // pn_delivery_t *dlv = pn_event_delivery(event); if (pn_delivery_updated(dlv) && pn_delivery_remote_state(dlv)) { uint64_t rs = pn_delivery_remote_state(dlv); int done = 1; switch (rs) { case PN_RECEIVED: // This is not a terminal state - it is informational, and the // peer is still processing the message. done = 0; break; case PN_ACCEPTED: pn_delivery_settle(dlv); if (!quiet) fprintf(stdout, "Send complete!\n"); break; case PN_REJECTED: case PN_RELEASED: case PN_MODIFIED: pn_delivery_settle(dlv); fprintf(stderr, "Message not accepted - code:%lu\n", (unsigned long)rs); break; default: // ??? no other terminal states defined, so ignore anything else pn_delivery_settle(dlv); fprintf(stderr, "Unknown delivery failure - code=%lu\n", (unsigned long)rs); break; } if (done) { // initiate clean shutdown of the endpoints pn_link_t *link = pn_delivery_link(dlv); pn_session_t *ssn = pn_link_session(link); pn_link_close(link); pn_session_close(ssn); pn_connection_close(pn_session_connection(ssn)); } } } break; case PN_TRANSPORT_ERROR: { // The connection to the peer failed. // pn_transport_t *tport = pn_event_transport(event); pn_condition_t *cond = pn_transport_condition(tport); fprintf(stderr, "Network transport failed!\n"); if (pn_condition_is_set(cond)) { const char *name = pn_condition_get_name(cond); const char *desc = pn_condition_get_description(cond); fprintf(stderr, " Error: %s Description: %s\n", (name) ? name : "<error name not provided>", (desc) ? desc : "<no description provided>"); } // pn_reactor_process() will exit with a false return value, stopping // the main loop. } break; default: break; } }
/** * Inbound Delivery Handler */ static void router_rx_handler(void* context, dx_link_t *link, pn_delivery_t *delivery) { dx_router_t *router = (dx_router_t*) context; pn_link_t *pn_link = pn_delivery_link(delivery); dx_message_t *msg; int valid_message = 0; // // Receive the message into a local representation. If the returned message // pointer is NULL, we have not yet received a complete message. // sys_mutex_lock(router->lock); msg = dx_message_receive(delivery); sys_mutex_unlock(router->lock); if (!msg) return; // // Validate the message through the Properties section // valid_message = dx_message_check(msg, DX_DEPTH_PROPERTIES); pn_link_advance(pn_link); pn_link_flow(pn_link, 1); if (valid_message) { dx_field_iterator_t *iter = dx_message_field_iterator(msg, DX_FIELD_TO); dx_router_link_t *rlink; if (iter) { dx_field_iterator_reset(iter, ITER_VIEW_NO_HOST); sys_mutex_lock(router->lock); int result = hash_retrieve(router->out_hash, iter, (void*) &rlink); dx_field_iterator_free(iter); if (result == 0) { // // To field is valid and contains a known destination. Enqueue on // the output fifo for the next-hop-to-destination. // pn_link_t* pn_outlink = dx_link_pn(rlink->link); DEQ_INSERT_TAIL(rlink->out_fifo, msg); pn_link_offered(pn_outlink, DEQ_SIZE(rlink->out_fifo)); dx_link_activate(rlink->link); } else { // // To field contains an unknown address. Release the message. // pn_delivery_update(delivery, PN_RELEASED); pn_delivery_settle(delivery); } sys_mutex_unlock(router->lock); } } else { // // Message is invalid. Reject the message. // pn_delivery_update(delivery, PN_REJECTED); pn_delivery_settle(delivery); pn_delivery_set_context(delivery, 0); dx_free_message(msg); } }
bool BufferedTransfer::write(pn_link_t* link) { pn_link_send(link, &data[0], data.size()); return pn_link_advance(link); }