Пример #1
0
/**
 * New Outgoing Link Handler
 */
static int router_outgoing_link_handler(void* context, dx_link_t *link)
{
    dx_router_t *router  = (dx_router_t*) context;
    pn_link_t   *pn_link = dx_link_pn(link);
    const char  *r_tgt   = pn_terminus_get_address(pn_link_remote_target(pn_link));

    sys_mutex_lock(router->lock);
    dx_router_link_t *rlink = new_dx_router_link_t();
    rlink->link = link;
    DEQ_INIT(rlink->out_fifo);
    dx_link_set_context(link, rlink);

    dx_field_iterator_t *iter = dx_field_iterator_string(r_tgt, ITER_VIEW_NO_HOST);
    int result = hash_insert(router->out_hash, iter, rlink);
    dx_field_iterator_free(iter);

    if (result == 0) {
        pn_terminus_copy(pn_link_source(pn_link), pn_link_remote_source(pn_link));
        pn_terminus_copy(pn_link_target(pn_link), pn_link_remote_target(pn_link));
        pn_link_open(pn_link);
        sys_mutex_unlock(router->lock);
        dx_log(module, LOG_TRACE, "Registered new local address: %s", r_tgt);
        return 0;
    }

    dx_log(module, LOG_TRACE, "Address '%s' not registered as it already exists", r_tgt);
    pn_link_close(pn_link);
    sys_mutex_unlock(router->lock);
    return 0;
}
Пример #2
0
sender session::open_sender(const std::string &addr, const sender_options &so) {
    std::string name = so.get_name() ? *so.get_name() : next_link_name(connection());
    pn_link_t *lnk = pn_sender(pn_object(), name.c_str());
    pn_terminus_set_address(pn_link_target(lnk), addr.c_str());
    sender snd(make_wrapper<sender>(lnk));
    snd.open(so);
    return snd;
}
Пример #3
0
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;
  }
}
Пример #4
0
 void apply(sender& s) {
     if (s.uninitialized()) {
         if (delivery_mode.set) set_delivery_mode(s, delivery_mode.value);
         if (handler.set && handler.value) set_handler(s, *handler.value);
         if (auto_settle.set) get_context(s).auto_settle = auto_settle.value;
         if (source.set) {
             proton::source local_s(make_wrapper<proton::source>(pn_link_source(unwrap(s))));
             source.value.apply(local_s);
         }
         if (target.set) {
             proton::target local_t(make_wrapper<proton::target>(pn_link_target(unwrap(s))));
             target.value.apply(local_t);
         }
     }
 }
Пример #5
0
/**
 * New Incoming Link Handler
 */
static int router_incoming_link_handler(void* context, dx_link_t *link)
{
    dx_router_t    *router  = (dx_router_t*) context;
    dx_link_item_t *item    = new_dx_link_item_t();
    pn_link_t      *pn_link = dx_link_pn(link);

    if (item) {
        DEQ_ITEM_INIT(item);
        item->link = link;

        sys_mutex_lock(router->lock);
        DEQ_INSERT_TAIL(router->in_links, item);
        sys_mutex_unlock(router->lock);

        pn_terminus_copy(pn_link_source(pn_link), pn_link_remote_source(pn_link));
        pn_terminus_copy(pn_link_target(pn_link), pn_link_remote_target(pn_link));
        pn_link_flow(pn_link, 8);
        pn_link_open(pn_link);
    } else {
        pn_link_close(pn_link);
    }
    return 0;
}
Пример #6
0
pn_terminus_t *qd_link_target(qd_link_t *link)
{
    return pn_link_target(link->pn_link);
}
Пример #7
0
terminus& link::target() const { return *terminus::cast(pn_link_target(pn_cast(this))); }
Пример #8
0
terminus link::local_target() const { return pn_link_target(pn_object()); }
Пример #9
0
/* runs the protocol engine, allowing it to handle TCP socket I/O and timer
 * events in the background.
*/
static void *amqp1_thread(void *arg)
{
	DBGPRINTF("omamqp1: Protocol thread started\n");

	pn_handler_t *handler = (pn_handler_t *)arg;
	protocolState_t *ps = PROTOCOL_STATE(handler);
	const configSettings_t *cfg = ps->config;

	// have pn_reactor_process() exit after 5 sec to poll for commands
	pn_reactor_set_timeout(ps->reactor, 5000);
	pn_reactor_start(ps->reactor);

	while (!ps->stopped) {
	    // setup a connection:
	    const char *host = pn_url_get_host(cfg->url);
	    const char *port = pn_url_get_port(cfg->url);
	    if (!port) port = "5672";

#if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 13
	    ps->conn = pn_reactor_connection_to_host(ps->reactor,
	                                             host,
	                                             port,
	                                             handler);
	    pn_connection_set_hostname(ps->conn, host);
#else
	    {
	        char host_addr[300];
	        ps->conn = pn_reactor_connection(ps->reactor, handler);
	        snprintf(host_addr, sizeof(host_addr), "%s:%s", host, port);
	        pn_connection_set_hostname(ps->conn, host_addr);
	    }
#endif
	    pn_connection_set_container(ps->conn, "rsyslogd-omamqp1");

#if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10
	    // proton version <= 0.9 did not support Cyrus SASL
	    const char *user = cfg->username
	        ? (char *)cfg->username
	        : pn_url_get_username(cfg->url);
	    if (user)
	        pn_connection_set_user(ps->conn, user);

	    const char *pword = cfg->password
	        ? (char *) cfg->password
	        : pn_url_get_password(cfg->url);
	    if (pword)
	        pn_connection_set_password(ps->conn, pword);
#endif
	    pn_connection_open(ps->conn);
	    pn_session_t *ssn = pn_session(ps->conn);
	    pn_session_open(ssn);
	    ps->sender = pn_sender(ssn, (char *)cfg->target);
	    pn_link_set_snd_settle_mode(ps->sender, PN_SND_UNSETTLED);
	    char *addr = (char *)ps->config->target;
	    pn_terminus_set_address(pn_link_target(ps->sender), addr);
	    pn_terminus_set_address(pn_link_source(ps->sender), addr);
	    pn_link_open(ps->sender);

	    // run the protocol engine until the connection closes or thread is shut down
	    sbool engine_running = true;
	    while (engine_running) {
	        engine_running = pn_reactor_process(ps->reactor);
	        _poll_command(ps);
	    }

	    DBGPRINTF("omamqp1: reactor finished\n");

	    _abort_command(ps);   // unblock main thread if necessary

	    // delay reconnectDelay seconds before re-connecting:
	    int delay = ps->config->reconnectDelay;
	    while (delay-- > 0 && !ps->stopped) {
	        srSleep(1, 0);
	        _poll_command(ps);
	    }
	}
	pn_reactor_stop(ps->reactor);

	// stop command is now done:
	threadIPC_t *ipc = ps->ipc;
	pthread_mutex_lock(&ipc->lock);
	ipc->result = RS_RET_OK;
	ipc->command = COMMAND_DONE;
	pthread_cond_signal(&ipc->condition);
	pthread_mutex_unlock(&ipc->lock);

	DBGPRINTF("omamqp1: Protocol thread stopped\n");

	return 0;
}
Пример #10
0
void SenderContext::configure() const
{
    configure(pn_link_target(sender));
}
Пример #11
0
void sender_dispatch(pn_handler_t *h, pn_event_t *event, pn_event_type_t type)
{
  sender_context_t *sc = sender_context(h);

  switch (type) {
  case PN_CONNECTION_INIT:
    {
      pn_connection_t *conn = pn_event_connection(event);
      pn_connection_set_container(conn, pn_string_get(sc->container_id));
      pn_connection_set_hostname(conn, pn_string_get(sc->hostname));
      pn_connection_open(conn);
      pn_session_t *ssn = pn_session(conn);
      pn_session_open(ssn);
      pn_link_t *snd = pn_sender(ssn, "sender");
      const char *path = pn_url_get_path(sc->send_url);
      if (path && strlen(path)) {
        pn_terminus_set_address(pn_link_target(snd), path);
        pn_terminus_set_address(pn_link_source(snd), path);
      }
      pn_link_open(snd);
    }
    break;
  case PN_LINK_FLOW:
    {
      pn_link_t *snd = pn_event_link(event);
      while (pn_link_credit(snd) > 0 && sc->sent < sc->opts->msg_count) {
        if (sc->sent == 0)
          statistics_start(sc->stats);

        char tag[8];
        void *ptr = &tag;
        *((uint64_t *) ptr) = sc->sent;
        pn_delivery_t *dlv = pn_delivery(snd, pn_dtag(tag, 8));

        // setup the message to send
        pn_message_t *msg = sc->message;
        pn_message_set_address(msg, sc->opts->targets.addresses[0]);
        sc->id.u.as_ulong = sc->sent;
        pn_message_set_correlation_id(msg, sc->id);
        pn_message_set_creation_time(msg, msgr_now());

        size_t size = sc->encoded_data_size;
        int err = pn_message_encode(msg, sc->encoded_data, &size);
        check(err == 0, "message encoding error");
        pn_link_send(snd, sc->encoded_data, size);
        pn_delivery_settle(dlv);
        sc->sent++;
      }
      if (sc->sent == sc->opts->msg_count && !sc->opts->get_replies) {
        pn_link_close(snd);
        pn_connection_t *conn = pn_event_connection(event);
        pn_connection_close(conn);
      }
    }
    break;
  case PN_LINK_INIT:
    {
      pn_link_t *link = pn_event_link(event);
      if (pn_link_is_receiver(link)) {
        // Response messages link.  Could manage credit and deliveries in this handler but
        // a dedicated handler also works.
        pn_handler_t *replyto = replyto_handler(sc);
        pn_flowcontroller_t *fc = pn_flowcontroller(1024);
        pn_handler_add(replyto, fc);
        pn_decref(fc);
        pn_handshaker_t *handshaker = pn_handshaker();
        pn_handler_add(replyto, handshaker);
        pn_decref(handshaker);
        pn_record_t *record = pn_link_attachments(link);
        pn_record_set_handler(record, replyto);
        pn_decref(replyto);
      }
    }
    break;
  case PN_CONNECTION_LOCAL_CLOSE:
    {
      statistics_report(sc->stats, sc->sent, sc->received);
    }
    break;
  default:
    break;
  }
}
Пример #12
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;
    }
}
Пример #13
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;
}