示例#1
0
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);
}
示例#2
0
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;
}
示例#3
0
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);
}
示例#4
0
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);
  }
}
示例#5
0
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);
}
示例#6
0
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);
}
示例#7
0
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);
}
示例#8
0
文件: Relay.cpp 项目: ChugR/qpid-cpp
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);

}
示例#9
0
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);
}
示例#10
0
文件: router_node.c 项目: ncdc/qpid
/**
 * 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);
}
示例#11
0
bool link::advance() {
    return pn_link_advance(pn_object());
}
示例#12
0
/**
 * 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);
    }
}
示例#13
0
// 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);
}
示例#14
0
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;
}
示例#15
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;
    }
}
示例#16
0
文件: router_node.c 项目: ncdc/qpid
/**
 * 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);
    }
}
示例#17
0
文件: Relay.cpp 项目: ChugR/qpid-cpp
bool BufferedTransfer::write(pn_link_t* link)
{
    pn_link_send(link, &data[0], data.size());
    return pn_link_advance(link);
}