Example #1
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;
  }
}
Example #2
0
/* Common handler for simple client/server interactions,  */
static pn_event_type_t common_handler(test_handler_t *th, pn_event_t *e) {
  pn_connection_t *c = pn_event_connection(e);
  pn_listener_t *l = pn_event_listener(e);

  switch (pn_event_type(e)) {

    /* Stop on these events */
   case PN_TRANSPORT_CLOSED:
   case PN_PROACTOR_INACTIVE:
   case PN_PROACTOR_TIMEOUT:
   case PN_LISTENER_OPEN:
    return pn_event_type(e);

   case PN_LISTENER_ACCEPT:
    last_accepted = pn_connection();
    pn_listener_accept2(l, last_accepted, NULL);
    pn_listener_close(l);       /* Only accept one connection */
    return PN_EVENT_NONE;

   case PN_CONNECTION_REMOTE_OPEN:
    pn_connection_open(c);      /* Return the open (no-op if already open) */
    return PN_EVENT_NONE;

   case PN_SESSION_REMOTE_OPEN:
    pn_session_open(pn_event_session(e));
    return PN_EVENT_NONE;

   case PN_LINK_REMOTE_OPEN:
    pn_link_open(pn_event_link(e));
    return PN_EVENT_NONE;

   case PN_CONNECTION_REMOTE_CLOSE:
    pn_connection_close(c);     /* Return the close */
    return PN_EVENT_NONE;

    /* Ignore these events */
   case PN_CONNECTION_BOUND:
   case PN_CONNECTION_INIT:
   case PN_CONNECTION_LOCAL_CLOSE:
   case PN_CONNECTION_LOCAL_OPEN:
   case PN_LINK_INIT:
   case PN_LINK_LOCAL_OPEN:
   case PN_LISTENER_CLOSE:
   case PN_SESSION_INIT:
   case PN_SESSION_LOCAL_OPEN:
   case PN_TRANSPORT:
   case PN_TRANSPORT_ERROR:
   case PN_TRANSPORT_HEAD_CLOSED:
   case PN_TRANSPORT_TAIL_CLOSED:
    return PN_EVENT_NONE;

   default:
    TEST_ERRORF(th->t, "unexpected event %s", pn_event_type_name(pn_event_type(e)));
    return PN_EVENT_NONE;                   /* Fail the test but keep going */
  }
}
void connection::open(const connection_options &opts) {
    connector *connector = dynamic_cast<class connector*>(
        connection_context::get(pn_object()).handler.get());
    if (connector)
        // connector has an internal copy of opts
        connector->apply_options();
    else
        opts.apply(*this);
    pn_connection_open(pn_object());
}
void messaging_adapter::on_connection_remote_open(proton_event &pe) {
    pn_connection_t *conn = pn_event_connection(pe.pn_event());
    connection c(make_wrapper(conn));
    transport t(make_wrapper(pn_event_transport(pe.pn_event())));
    delegate_.on_transport_open(t);
    delegate_.on_connection_open(c);
    if (!is_local_open(pn_connection_state(conn)) && is_local_unititialised(pn_connection_state(conn))) {
        pn_connection_open(conn);
    }
}
void messaging_adapter::on_connection_remote_open(event &e) {
    proton_event *pe = dynamic_cast<proton_event*>(&e);
    if (pe) {
        messaging_event mevent(messaging_event::CONNECTION_OPEN, *pe);
        on_connection_open(mevent);
        pn_connection_t *connection = pn_event_connection(pe->pn_event());
        if (!is_local_open(pn_connection_state(connection)) && is_local_unititialised(pn_connection_state(connection))) {
            pn_connection_open(connection);
        }
    }
}
Example #6
0
static pn_event_type_t ssl_server_handler(test_handler_t *h, pn_event_t *e) {
  switch (pn_event_type(e)) {
   case PN_CONNECTION_BOUND:
    return ssl_handler(h, e);
   case PN_CONNECTION_REMOTE_OPEN: {
     pn_event_type_t et = ssl_handler(h, e);
     pn_connection_open(pn_event_connection(e));
     return et;
   }
   default:
    return listen_handler(h, e);
  }
}
Example #7
0
void qd_policy_amqp_open(void *context, bool discard)
{
    qd_connection_t *qd_conn = (qd_connection_t *)context;
    if (!discard) {
        pn_connection_t *conn = qd_connection_pn(qd_conn);
        qd_dispatch_t *qd = qd_conn->server->qd;
        qd_policy_t *policy = qd->policy;
        bool connection_allowed = true;

        if (policy->enableAccessRules) {
            // Open connection or not based on policy.
            pn_transport_t *pn_trans = pn_connection_transport(conn);
            const char *hostip = qdpn_connector_hostip(qd_conn->pn_cxtr);
            const char *pcrh = pn_connection_remote_hostname(conn);
            const char *app = (pcrh ? pcrh : "");
            const char *conn_name = qdpn_connector_name(qd_conn->pn_cxtr);
#define SETTINGS_NAME_SIZE 256
            char settings_name[SETTINGS_NAME_SIZE];
            uint32_t conn_id = qd_conn->connection_id;
            qd_conn->policy_settings = NEW(qd_policy_settings_t); // TODO: memory pool for settings
            memset(qd_conn->policy_settings, 0, sizeof(qd_policy_settings_t));

            if (qd_policy_open_lookup_user(policy, qd_conn->user_id, hostip, app, conn_name,
                                           settings_name, SETTINGS_NAME_SIZE, conn_id,
                                           qd_conn->policy_settings) &&
                settings_name[0]) {
                // This connection is allowed by policy.
                // Apply transport policy settings
                if (qd_conn->policy_settings->maxFrameSize > 0)
                    pn_transport_set_max_frame(pn_trans, qd_conn->policy_settings->maxFrameSize);
                if (qd_conn->policy_settings->maxSessions > 0)
                    pn_transport_set_channel_max(pn_trans, qd_conn->policy_settings->maxSessions - 1);
            } else {
                // This connection is denied by policy.
                connection_allowed = false;
            }
        } else {
            // No policy implies automatic policy allow
            // Note that connections not governed by policy have no policy_settings.
        }
        if (connection_allowed) {
            if (pn_connection_state(conn) & PN_LOCAL_UNINIT)
                pn_connection_open(conn);
            policy_notify_opened(qd_conn->open_container, qd_conn, qd_conn->context);
        } else {
            qd_policy_private_deny_amqp_connection(conn, RESOURCE_LIMIT_EXCEEDED, CONNECTION_DISALLOWED);
        }
    }
    qd_connection_set_event_stall(qd_conn, false);
}
Example #8
0
pn_connection_t *pn_messenger_domain(pn_messenger_t *messenger, const char *domain)
{
  char buf[domain ? strlen(domain) + 1 : 1];
  if (domain) {
    strcpy(buf, domain);
  } else {
    buf[0] = '\0';
  }
  char *user = NULL;
  char *pass = NULL;
  char *host = "0.0.0.0";
  char *port = "5672";
  parse_url(buf, &user, &pass, &host, &port);

  for (int i = 0; i < messenger->size; i++) {
    pn_connection_t *connection = pn_connector_connection(messenger->connectors[i]);
    const char *container = pn_connection_remote_container(connection);
    const char *hostname = pn_connection_hostname(connection);
    if (pn_streq(container, domain) || pn_streq(hostname, domain))
      return connection;
  }

  pn_connector_t *connector = pn_connector(messenger->driver, host, port, NULL);
  if (!connector) return NULL;
  messenger->connectors[messenger->size++] = connector;
  pn_sasl_t *sasl = pn_connector_sasl(connector);
  if (user) {
    pn_sasl_plain(sasl, user, pass);
  } else {
    pn_sasl_mechanisms(sasl, "ANONYMOUS");
    pn_sasl_client(sasl);
  }
  pn_connection_t *connection = pn_connection();
  pn_connection_set_container(connection, messenger->name);
  pn_connection_set_hostname(connection, domain);
  pn_connection_open(connection);
  pn_connector_set_connection(connector, connection);

  return connection;
}
Example #9
0
void pn_messenger_endpoints(pn_messenger_t *messenger, pn_connection_t *conn)
{
  if (pn_connection_state(conn) | PN_LOCAL_UNINIT) {
    pn_connection_open(conn);
  }

  pn_session_t *ssn = pn_session_head(conn, PN_LOCAL_UNINIT);
  while (ssn) {
    pn_session_open(ssn);
    ssn = pn_session_next(ssn, PN_LOCAL_UNINIT);
  }

  pn_link_t *link = pn_link_head(conn, PN_LOCAL_UNINIT);
  while (link) {
    pn_set_source(link, pn_remote_source(link));
    pn_set_target(link, pn_remote_target(link));
    pn_link_open(link);
    link = pn_link_next(link, PN_LOCAL_UNINIT);
  }

  pn_messenger_flow(messenger);

  ssn = pn_session_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  while (ssn) {
    pn_session_close(ssn);
    ssn = pn_session_next(ssn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  }

  link = pn_link_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  while (link) {
    pn_link_close(link);
    link = pn_link_next(link, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  }

  if (pn_connection_state(conn) == (PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED)) {
    pn_connection_close(conn);
  }
}
Example #10
0
void Interconnect::process()
{
    QPID_LOG(trace, id << " processing interconnect");
    if (closeRequested) {
        close();
    } else {
        if ((pn_connection_state(connection) & UNINIT) == UNINIT) {
            QPID_LOG_CAT(debug, model, id << " interconnect open initiated");
            pn_connection_set_container(connection, getBroker().getFederationTag().c_str());
            setProperties(connection);
            pn_connection_open(connection);
            out.connectionEstablished();
            setInterconnectDomain(domain);
        }
        if (!isOpened && (pn_connection_state(connection) & PN_REMOTE_ACTIVE)) {
            QPID_LOG_CAT(debug, model, id << " interconnect open completed, attaching link");
            isOpened = true;
            readPeerProperties();
            const char* containerid(pn_connection_remote_container(connection));
            if (containerid) {
                setContainerId(std::string(containerid));
            }
            opened();
            getBroker().getConnectionObservers().opened(*this);
            pn_session_t* s = pn_session(connection);
            pn_session_open(s);
            boost::shared_ptr<Session> ssn(new Session(s, *this, out));
            sessions[s] = ssn;

            pn_link_t* l = incoming ? pn_receiver(s, name.c_str()) : pn_sender(s, name.c_str());
            pn_link_open(l);
            ssn->attach(l, source, target, relay);
        }
        Connection::process();
    }
}
Example #11
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;
}
Example #12
0
void connection::open(const connection_options &opts) {
    opts.apply_unbound(*this);
    pn_connection_open(pn_object());
}
Example #13
0
void Connection::process()
{
    QPID_LOG(trace, id << " process()");
    if ((pn_connection_state(connection) & REQUIRES_OPEN) == REQUIRES_OPEN) {
        QPID_LOG_CAT(debug, model, id << " connection opened");
        pn_connection_set_container(connection, broker.getFederationTag().c_str());
        pn_connection_open(connection);
    }

    for (pn_session_t* s = pn_session_head(connection, REQUIRES_OPEN); s; s = pn_session_next(s, REQUIRES_OPEN)) {
        QPID_LOG_CAT(debug, model, id << " session begun");
        pn_session_open(s);
        boost::shared_ptr<Session> ssn(new Session(s, broker, *this, out));
        sessions[s] = ssn;
    }
    for (pn_link_t* l = pn_link_head(connection, REQUIRES_OPEN); l; l = pn_link_next(l, REQUIRES_OPEN)) {
        pn_link_open(l);

        Sessions::iterator session = sessions.find(pn_link_session(l));
        if (session == sessions.end()) {
            QPID_LOG(error, id << " Link attached on unknown session!");
        } else {
            try {
                session->second->attach(l);
                QPID_LOG_CAT(debug, protocol, id << " link " << l << " attached on " << pn_link_session(l));
            } catch (const std::exception& e) {
                QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what());
                //TODO: set error details on detach when that is exposed via engine API
                pn_link_close(l);
            }
        }
    }

    //handle deliveries
    for (pn_delivery_t* delivery = pn_work_head(connection); delivery; delivery = pn_work_next(delivery)) {
        pn_link_t* link = pn_delivery_link(delivery);
        if (pn_link_is_receiver(link)) {
            Sessions::iterator i = sessions.find(pn_link_session(link));
            if (i != sessions.end()) {
                i->second->readable(link, delivery);
            } else {
                pn_delivery_update(delivery, PN_REJECTED);
            }
        } else { //i.e. SENDER
            Sessions::iterator i = sessions.find(pn_link_session(link));
            if (i != sessions.end()) {
                QPID_LOG(trace, id << " handling outgoing delivery for " << link << " on session " << pn_link_session(link));
                i->second->writable(link, delivery);
            } else {
                QPID_LOG(error, id << " Got delivery for non-existent session: " << pn_link_session(link) << ", link: " << link);
            }
        }
    }


    for (pn_link_t* l = pn_link_head(connection, REQUIRES_CLOSE); l; l = pn_link_next(l, REQUIRES_CLOSE)) {
        pn_link_close(l);
        Sessions::iterator session = sessions.find(pn_link_session(l));
        if (session == sessions.end()) {
            QPID_LOG(error, id << " peer attempted to detach link on unknown session!");
        } else {
            session->second->detach(l);
            QPID_LOG_CAT(debug, model, id << " link detached");
        }
    }
    for (pn_session_t* s = pn_session_head(connection, REQUIRES_CLOSE); s; s = pn_session_next(s, REQUIRES_CLOSE)) {
        pn_session_close(s);
        Sessions::iterator i = sessions.find(s);
        if (i != sessions.end()) {
            i->second->close();
            sessions.erase(i);
            QPID_LOG_CAT(debug, model, id << " session ended");
        } else {
            QPID_LOG(error, id << " peer attempted to close unrecognised session");
        }
    }
    if ((pn_connection_state(connection) & REQUIRES_CLOSE) == REQUIRES_CLOSE) {
        QPID_LOG_CAT(debug, model, id << " connection closed");
        pn_connection_close(connection);
    }
}
Example #14
0
void connection::open() {
    pn_connection_open(pn_cast(this));
}
Example #15
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;
}
Example #16
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;
  }
}
Example #17
0
void client_callback(pn_connector_t *ctor)
{
  struct client_context *ctx = pn_connector_context(ctor);
  if (pn_connector_closed(ctor)) {
    ctx->done = true;
  }

  pn_sasl_t *sasl = pn_connector_sasl(ctor);

  while (pn_sasl_state(sasl) != PN_SASL_PASS) {
    pn_sasl_state_t st = pn_sasl_state(sasl);
    switch (st) {
    case PN_SASL_IDLE:
      return;
    case PN_SASL_CONF:
      if (ctx->mechanism && !strcmp(ctx->mechanism, "PLAIN")) {
        pn_sasl_plain(sasl, ctx->username, ctx->password);
      } else {
        pn_sasl_mechanisms(sasl, ctx->mechanism);
        pn_sasl_client(sasl);
      }
      break;
    case PN_SASL_STEP:
      if (pn_sasl_pending(sasl)) {
        fprintf(stderr, "challenge failed\n");
        ctx->done = true;
      }
      return;
    case PN_SASL_FAIL:
      fprintf(stderr, "authentication failed\n");
      ctx->done = true;
      return;
    case PN_SASL_PASS:
      break;
    }
  }

  pn_connection_t *connection = pn_connector_connection(ctor);
  char tagstr[1024];
  char msg[ctx->size];
  char data[ctx->size + 16];
  for (int i = 0; i < ctx->size; i++) {
    msg[i] = 'x';
  }
  size_t ndata = pn_message_data(data, ctx->size + 16, msg, ctx->size);

  if (!ctx->init) {
    ctx->init = true;

    char container[1024];
    if (gethostname(container, 1024)) pn_fatal("hostname lookup failed");

    pn_connection_set_container(connection, container);
    pn_connection_set_hostname(connection, ctx->hostname);

    pn_session_t *ssn = pn_session(connection);
    pn_connection_open(connection);
    pn_session_open(ssn);

    if (ctx->send_count) {
      pn_link_t *snd = pn_sender(ssn, "sender");
      pn_set_target(snd, ctx->address);
      pn_link_open(snd);

      char buf[16];
      for (int i = 0; i < ctx->send_count; i++) {
        sprintf(buf, "%x", i);
        pn_delivery(snd, pn_dtag(buf, strlen(buf)));
      }
    }

    if (ctx->recv_count) {
      pn_link_t *rcv = pn_receiver(ssn, "receiver");
      pn_set_source(rcv, ctx->address);
      pn_link_open(rcv);
      pn_flow(rcv, ctx->recv_count < ctx->high ? ctx->recv_count : ctx->high);
    }
  }

  pn_delivery_t *delivery = pn_work_head(connection);
  while (delivery)
  {
    pn_delivery_tag_t tag = pn_delivery_tag(delivery);
    pn_quote_data(tagstr, 1024, tag.bytes, tag.size);
    pn_link_t *link = pn_link(delivery);
    if (pn_writable(delivery)) {
      pn_send(link, data, ndata);
      if (pn_advance(link)) {
        if (!ctx->quiet) printf("sent delivery: %s\n", tagstr);
      }
    } else if (pn_readable(delivery)) {
      if (!ctx->quiet) {
        printf("received delivery: %s\n", tagstr);
        printf("  payload = \"");
      }
      while (true) {
        size_t n = pn_recv(link, msg, 1024);
        if (n == PN_EOS) {
          pn_advance(link);
          pn_disposition(delivery, PN_ACCEPTED);
          pn_settle(delivery);
          if (!--ctx->recv_count) {
            pn_link_close(link);
          }
          break;
        } else if (!ctx->quiet) {
          pn_print_data(msg, n);
        }
      }
      if (!ctx->quiet) printf("\"\n");

      if (pn_credit(link) < ctx->low && pn_credit(link) < ctx->recv_count) {
        pn_flow(link, (ctx->recv_count < ctx->high ? ctx->recv_count : ctx->high) - pn_credit(link));
      }
    }

    if (pn_updated(delivery)) {
      if (!ctx->quiet) printf("disposition for %s: %u\n", tagstr, pn_remote_disposition(delivery));
      pn_clear(delivery);
      pn_settle(delivery);
      if (!--ctx->send_count) {
        pn_link_close(link);
      }
    }

    delivery = pn_work_next(delivery);
  }

  if (!ctx->send_count && !ctx->recv_count) {
    printf("closing\n");
    // XXX: how do we close the session?
    //pn_close((pn_endpoint_t *) ssn);
    pn_connection_close(connection);
  }

  if (pn_connection_state(connection) == (PN_LOCAL_CLOSED | PN_REMOTE_CLOSED)) {
    ctx->done = true;
  }
}
Example #18
0
void server_callback(pn_connector_t *ctor)
{
  pn_sasl_t *sasl = pn_connector_sasl(ctor);

  while (pn_sasl_state(sasl) != PN_SASL_PASS) {
    switch (pn_sasl_state(sasl)) {
    case PN_SASL_IDLE:
      return;
    case PN_SASL_CONF:
      pn_sasl_mechanisms(sasl, "PLAIN ANONYMOUS");
      pn_sasl_server(sasl);
      break;
    case PN_SASL_STEP:
      {
        size_t n = pn_sasl_pending(sasl);
        char iresp[n];
        pn_sasl_recv(sasl, iresp, n);
        printf("%s", pn_sasl_remote_mechanisms(sasl));
        printf(" response = ");
        pn_print_data(iresp, n);
        printf("\n");
        pn_sasl_done(sasl, PN_SASL_OK);
        pn_connector_set_connection(ctor, pn_connection());
      }
      break;
    case PN_SASL_PASS:
      break;
    case PN_SASL_FAIL:
      return;
    }
  }

  pn_connection_t *conn = pn_connector_connection(ctor);
  struct server_context *ctx = pn_connector_context(ctor);
  char tagstr[1024];
  char msg[10*1024];
  char data[ctx->size + 16];
  for (int i = 0; i < ctx->size; i++) {
    msg[i] = 'x';
  }
  size_t ndata = pn_message_data(data, ctx->size + 16, msg, ctx->size);

  if (pn_connection_state(conn) == (PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE)) {
    pn_connection_open(conn);
  }

  pn_session_t *ssn = pn_session_head(conn, PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE);
  while (ssn) {
    pn_session_open(ssn);
    ssn = pn_session_next(ssn, PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE);
  }

  pn_link_t *link = pn_link_head(conn, PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE);
  while (link) {
    printf("%s, %s\n", pn_remote_source(link), pn_remote_target(link));
    pn_set_source(link, pn_remote_source(link));
    pn_set_target(link, pn_remote_target(link));
    pn_link_open(link);
    if (pn_is_receiver(link)) {
      pn_flow(link, 100);
    } else {
      pn_delivery(link, pn_dtag("blah", 4));
    }

    link = pn_link_next(link, PN_LOCAL_UNINIT | PN_REMOTE_ACTIVE);
  }

  pn_delivery_t *delivery = pn_work_head(conn);
  while (delivery)
  {
    pn_delivery_tag_t tag = pn_delivery_tag(delivery);
    pn_quote_data(tagstr, 1024, tag.bytes, tag.size);
    pn_link_t *link = pn_link(delivery);
    if (pn_readable(delivery)) {
      if (!ctx->quiet) {
        printf("received delivery: %s\n", tagstr);
        printf("  payload = \"");
      }
      while (true) {
        ssize_t n = pn_recv(link, msg, 1024);
        if (n == PN_EOS) {
          pn_advance(link);
          pn_disposition(delivery, PN_ACCEPTED);
          break;
        } else if (!ctx->quiet) {
          pn_print_data(msg, n);
        }
      }
      if (!ctx->quiet) printf("\"\n");
      if (pn_credit(link) < 50) pn_flow(link, 100);
    } else if (pn_writable(delivery)) {
      pn_send(link, data, ndata);
      if (pn_advance(link)) {
        if (!ctx->quiet) printf("sent delivery: %s\n", tagstr);
        char tagbuf[16];
        sprintf(tagbuf, "%i", ctx->count++);
        pn_delivery(link, pn_dtag(tagbuf, strlen(tagbuf)));
      }
    }

    if (pn_updated(delivery)) {
      if (!ctx->quiet) printf("disposition for %s: %u\n", tagstr, pn_remote_disposition(delivery));
      pn_settle(delivery);
    }

    delivery = pn_work_next(delivery);
  }

  if (pn_connection_state(conn) == (PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED)) {
    pn_connection_close(conn);
  }

  ssn = pn_session_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  while (ssn) {
    pn_session_close(ssn);
    ssn = pn_session_next(ssn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  }

  link = pn_link_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  while (link) {
    pn_link_close(link);
    link = pn_link_next(link, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED);
  }
}
Example #19
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;
    }
}