Exemple #1
0
/* Test waking up a connection that is idle */
static void test_connection_wake(test_t *t) {
  test_proactor_t tps[] =  { test_proactor(t, open_wake_handler), test_proactor(t,  listen_handler) };
  pn_proactor_t *client = tps[0].proactor;
  pn_listener_t *l = test_listen(&tps[1], "");

  pn_connection_t *c = pn_connection();
  pn_incref(c);                 /* Keep a reference for wake() after free */
  pn_proactor_connect2(client, c, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  TEST_CHECK(t, pn_proactor_get(client) == NULL); /* Should be idle */
  pn_connection_wake(c);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_WAKE, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* Both ends */
  /* The pn_connection_t is still valid so wake is legal but a no-op */
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_EVENT_NONE, TEST_PROACTORS_GET(tps)); /* No more wake */

  /* Verify we don't get a wake after close even if they happen together */
  pn_connection_t *c2 = pn_connection();
  pn_proactor_connect2(client, c2, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  pn_connection_wake(c2);
  pn_proactor_disconnect(client, NULL);
  pn_connection_wake(c2);

  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, test_proactors_run(&tps[0], 1));
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, test_proactors_run(&tps[0], 1));
  TEST_ETYPE_EQUAL(t, PN_EVENT_NONE, test_proactors_get(&tps[0], 1)); /* No late wake */

  TEST_PROACTORS_DESTROY(tps);
  /* The pn_connection_t is still valid so wake is legal but a no-op */
  pn_connection_wake(c);
  pn_decref(c);
}
Exemple #2
0
/* Make sure we clean up released connections and open sockets correctly */
static void test_release_free(test_t *t) {
  test_proactor_t tps[] = { test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) };
  pn_proactor_t *client = tps[0].proactor;
  pn_listener_t *l = test_listen(&tps[1], "");

  /* leave one connection to the proactor  */
  pn_proactor_connect2(client, NULL, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));

  /* release c1 and free immediately */
  pn_connection_t *c1 = pn_connection();
  pn_proactor_connect2(client, c1, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  pn_proactor_release_connection(c1); /* We free but socket should still be cleaned up */
  pn_connection_free(c1);
  TEST_CHECK(t, pn_proactor_get(client) == NULL); /* Should be idle */
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* Server closed */

  /* release c2 and but don't free till after proactor free */
  pn_connection_t *c2 = pn_connection();
  pn_proactor_connect2(client, c2, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  pn_proactor_release_connection(c2);
  TEST_CHECK(t, pn_proactor_get(client) == NULL); /* Should be idle */
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* Server closed */

  TEST_PROACTORS_DESTROY(tps);
  pn_connection_free(c2);

  /* Check freeing a listener or connection that was never given to a proactor */
  pn_listener_free(pn_listener());
  pn_connection_free(pn_connection());
}
Exemple #3
0
/* Tests for error handling */
static void test_errors(test_t *t) {
  test_proactor_t tps[] =  { test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) };
  pn_proactor_t *client = tps[0].proactor, *server = tps[1].proactor;

  /* Invalid connect/listen service name */
  pn_connection_t *c = pn_connection();
  pn_proactor_connect2(client, c, NULL, "127.0.0.1:xxx");
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_COND_DESC(t, "xxx", last_condition);
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  pn_proactor_listen(server, pn_listener(), "127.0.0.1:xxx", 1);
  TEST_PROACTORS_RUN(tps);
  TEST_HANDLER_EXPECT(&tps[1].handler, PN_LISTENER_CLOSE, 0); /* CLOSE only, no OPEN */
  TEST_COND_DESC(t, "xxx", last_condition);
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  /* Invalid connect/listen host name */
  c = pn_connection();
  pn_proactor_connect2(client, c, NULL, "nosuch.example.com:");
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_COND_DESC(t, "nosuch", last_condition);
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  test_handler_clear(&tps[1].handler, 0);
  pn_proactor_listen(server, pn_listener(), "nosuch.example.com:", 1);
  TEST_PROACTORS_RUN(tps);
  TEST_HANDLER_EXPECT(&tps[1].handler, PN_LISTENER_CLOSE, 0); /* CLOSE only, no OPEN */
  TEST_COND_DESC(t, "nosuch", last_condition);
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  /* Listen on a port already in use */
  pn_listener_t *l = pn_listener();
  pn_proactor_listen(server, l, ":0", 1);
  TEST_ETYPE_EQUAL(t, PN_LISTENER_OPEN, TEST_PROACTORS_RUN(tps));
  test_handler_clear(&tps[1].handler, 0);
  struct addrinfo laddr = listener_info(l);
  pn_proactor_listen(server, pn_listener(), laddr.connect, 1); /* Busy */
  TEST_PROACTORS_RUN(tps);
  TEST_HANDLER_EXPECT(&tps[1].handler, PN_LISTENER_CLOSE, 0); /* CLOSE only, no OPEN */
  TEST_COND_NAME(t, "proton:io", last_condition);
  pn_listener_close(l);
  TEST_ETYPE_EQUAL(t, PN_LISTENER_CLOSE, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  /* Connect with no listener */
  c = pn_connection();
  pn_proactor_connect2(client, c, NULL, laddr.connect);
  if (TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps))) {
    TEST_COND_DESC(t, "refused", last_condition);
    TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));
  }

  TEST_PROACTORS_DESTROY(tps);
}
Exemple #4
0
/* Test pn_proactor_disconnect */
static void test_disconnect(test_t *t) {
  test_proactor_t tps[] ={ test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) };
  pn_proactor_t *client = tps[0].proactor, *server = tps[1].proactor;

  /* Start two listeners */
  pn_listener_t *l = test_listen(&tps[1], "");
  pn_listener_t *l2 = test_listen(&tps[1], "");

  /* Only wait for one connection to remote-open before disconnect */
  pn_connection_t *c = pn_connection();
  pn_proactor_connect2(client, c, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  pn_connection_t *c2 = pn_connection();
  pn_proactor_connect2(client, c2, NULL, listener_info(l2).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  TEST_PROACTORS_DRAIN(tps);

  /* Disconnect the client proactor */
  pn_condition_t *cond = pn_condition();
  pn_condition_set_name(cond, "test-name");
  pn_condition_set_description(cond, "test-description");
  pn_proactor_disconnect(client, cond);
  /* Verify expected client side first */
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, test_proactors_run(&tps[0], 1));
  TEST_COND_NAME(t, "test-name", last_condition);
  TEST_COND_DESC(t, "test-description", last_condition);
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, test_proactors_run(&tps[0], 1));
  TEST_COND_NAME(t, "test-name", last_condition);
  TEST_COND_DESC(t, "test-description", last_condition);
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, test_proactors_run(&tps[0], 1));

  /* Now check server sees the disconnects */
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));

  /* Now disconnect the server end (the listeners) */
  pn_proactor_disconnect(server, cond);
  pn_condition_free(cond);

  TEST_ETYPE_EQUAL(t, PN_LISTENER_CLOSE, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_LISTENER_CLOSE, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  /* Make sure the proactors are still functional */
  pn_listener_t *l3 = test_listen(&tps[1], "");
  pn_proactor_connect2(client, NULL, NULL, listener_info(l3).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  pn_proactor_disconnect(client, NULL);

  TEST_PROACTORS_DRAIN(tps);
  TEST_PROACTORS_DESTROY(tps);
}
Exemple #5
0
/* Test various SSL connections between proactors*/
static void test_ssl(test_t *t) {
  if (!pn_ssl_present()) {
    TEST_LOGF(t, "Skip SSL test, no support");
    return;
  }

  test_proactor_t tps[] ={ test_proactor(t, ssl_client_handler), test_proactor(t, ssl_server_handler) };
  test_proactor_t *client = &tps[0], *server = &tps[1];
  pn_ssl_domain_t *cd = client->handler.ssl_domain = pn_ssl_domain(PN_SSL_MODE_CLIENT);
  pn_ssl_domain_t *sd =  server->handler.ssl_domain = pn_ssl_domain(PN_SSL_MODE_SERVER);
  TEST_CHECK(t, 0 == SET_CREDENTIALS(sd, "tserver"));
  pn_listener_t *l = test_listen(server, "");

  /* Basic SSL connection */
  pn_proactor_connect2(client->proactor, NULL, NULL, listener_info(l).connect);
  /* Open ok at both ends */
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  TEST_COND_EMPTY(t, last_condition);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  TEST_COND_EMPTY(t, last_condition);
  TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED);
  TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED);

  /* Verify peer with good hostname */
  TEST_INT_EQUAL(t, 0, pn_ssl_domain_set_trusted_ca_db(cd, CERTIFICATE("tserver")));
  TEST_INT_EQUAL(t, 0, pn_ssl_domain_set_peer_authentication(cd, PN_SSL_VERIFY_PEER_NAME, NULL));
  pn_connection_t *c = pn_connection();
  pn_connection_set_hostname(c, "test_server");
  pn_proactor_connect2(client->proactor, c, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  TEST_COND_EMPTY(t, last_condition);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  TEST_COND_EMPTY(t, last_condition);
  TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED);
  TEST_PROACTORS_RUN_UNTIL(tps, PN_TRANSPORT_CLOSED);

  /* Verify peer with bad hostname */
  c = pn_connection();
  pn_connection_set_hostname(c, "wrongname");
  pn_proactor_connect2(client->proactor, c, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_COND_NAME(t, "amqp:connection:framing-error",  last_condition);
  TEST_COND_DESC(t, "SSL",  last_condition);
  TEST_PROACTORS_DRAIN(tps);

  pn_ssl_domain_free(cd);
  pn_ssl_domain_free(sd);
  TEST_PROACTORS_DESTROY(tps);
}
int pn_messenger_tsync(pn_messenger_t *messenger, bool (*predicate)(pn_messenger_t *), int timeout)
{
  for (int i = 0; i < messenger->size; i++) {
    pn_connector_process(messenger->connectors[i]);
  }

  struct timeval now;
  if (gettimeofday(&now, NULL)) pn_fatal("gettimeofday failed\n");
  long int deadline = millis(now) + timeout;
  bool pred;

  while (true) {
    pred = predicate(messenger);
    int remaining = deadline - millis(now);
    if (pred || (timeout >= 0 && remaining < 0)) break;

    pn_driver_wait(messenger->driver, remaining);

    pn_listener_t *l;
    while ((l = pn_driver_listener(messenger->driver))) {
      pn_connector_t *c = pn_listener_accept(l);
      pn_sasl_t *sasl = pn_connector_sasl(c);
      pn_sasl_mechanisms(sasl, "ANONYMOUS");
      pn_sasl_server(sasl);
      pn_sasl_done(sasl, PN_SASL_OK);
      pn_connection_t *conn = pn_connection();
      pn_connection_set_container(conn, messenger->name);
      pn_connector_set_connection(c, conn);
      messenger->connectors[messenger->size++] = c;
    }

    pn_connector_t *c;
    while ((c = pn_driver_connector(messenger->driver))) {
      pn_connector_process(c);
      pn_connection_t *conn = pn_connector_connection(c);
      pn_messenger_endpoints(messenger, conn);
      if (pn_connector_closed(c)) {
        for (int i = 0; i < messenger->size; i++) {
          if (c == messenger->connectors[i]) {
            memmove(messenger->connectors + i, messenger->connectors + i + 1, messenger->size - i - 1);
            messenger->size--;
            pn_connector_free(c);
            pn_messenger_reclaim(messenger, conn);
            pn_connection_free(conn);
            pn_messenger_flow(messenger);
            break;
          }
        }
      } else {
        pn_connector_process(c);
      }
    }

    if (timeout >= 0) {
      if (gettimeofday(&now, NULL)) pn_fatal("gettimeofday failed\n");
    }
  }

  return pred ? 0 : PN_TIMEOUT;
}
connection_engine::connection_engine(class handler &h, const connection_options& opts) {
    connection_ = proton::connection(take_ownership(pn_connection()).get());
    pn_ptr<pn_transport_t> transport = take_ownership(pn_transport());
    pn_ptr<pn_collector_t> collector = take_ownership(pn_collector());
    if (!connection_ || !transport || !collector)
        throw proton::error("engine create");
    int err = pn_transport_bind(transport.get(), connection_.pn_object());
    if (err)
        throw error(msg() << "transport bind:" << pn_code(err));
    pn_connection_collect(connection_.pn_object(), collector.get());

    ctx_ = &connection_engine_context::get(connection_); // Creates context
    ctx_->engine_handler = &h;
    ctx_->transport = transport.release();
    ctx_->collector = collector.release();
    opts.apply(connection_);
    // Provide defaults for connection_id and link_prefix if not set.
    std::string cid = connection_.container_id();
    if (cid.empty()) {
        cid = make_id();
        pn_connection_set_container(connection_.pn_object(), cid.c_str());
    }
    id_generator &link_gen = connection_context::get(connection_).link_gen;
    if (link_gen.prefix().empty()) {
        link_gen.prefix(make_id()+"/");
    }
}
Exemple #8
0
/* Test that INACTIVE event is generated when last connections/listeners closes. */
static void test_inactive(test_t *t) {
  test_proactor_t tps[] =  { test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) };
  pn_proactor_t *client = tps[0].proactor, *server = tps[1].proactor;

  /* Listen, connect, disconnect */
  pn_listener_t *l = test_listen(&tps[1], "");
  pn_connection_t *c = pn_connection();
  pn_proactor_connect2(client, c, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  pn_connection_wake(c);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_WAKE, TEST_PROACTORS_RUN(tps));
  /* Expect TRANSPORT_CLOSED from client and server, INACTIVE from client */
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  /* Immediate timer generates INACTIVE on client (no connections) */
  pn_proactor_set_timeout(client, 0);
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_TIMEOUT, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  /* Connect, set-timer, disconnect */
  pn_proactor_set_timeout(client, 1000000);
  c = pn_connection();
  pn_proactor_connect2(client, c, NULL, listener_info(l).connect);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps));
  pn_connection_wake(c);
  TEST_ETYPE_EQUAL(t, PN_CONNECTION_WAKE, TEST_PROACTORS_RUN(tps));
  /* Expect TRANSPORT_CLOSED from client and server */
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));
  /* No INACTIVE till timer is cancelled */
  TEST_CHECK(t, pn_proactor_get(server) == NULL);
  pn_proactor_cancel_timeout(client);
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  /* Server won't be INACTIVE until listener is closed */
  TEST_CHECK(t, pn_proactor_get(server) == NULL);
  pn_listener_close(l);
  TEST_ETYPE_EQUAL(t, PN_LISTENER_CLOSE, TEST_PROACTORS_RUN(tps));
  TEST_ETYPE_EQUAL(t, PN_PROACTOR_INACTIVE, TEST_PROACTORS_RUN(tps));

  TEST_PROACTORS_DESTROY(tps);
}
Exemple #9
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 */
  }
}
Exemple #10
0
pn_connection_t *pn_reactor_connection(pn_reactor_t *reactor, pn_handler_t *handler) {
  assert(reactor);
  pn_connection_t *connection = pn_connection();
  pn_record_t *record = pn_connection_attachments(connection);
  pn_record_set_handler(record, handler);
  pn_connection_collect(connection, pn_reactor_collector(reactor));
  pn_list_add(pn_reactor_children(reactor), connection);
  pni_record_init_reactor(record, reactor);
  pn_decref(connection);
  return connection;
}
connection_engine::connection_engine(class container& cont, link_namer& namer, event_loop* loop) :
    handler_(0),
    connection_(make_wrapper(internal::take_ownership(pn_connection()).get())),
    transport_(make_wrapper(internal::take_ownership(pn_transport()).get())),
    collector_(internal::take_ownership(pn_collector()).get()),
    container_(cont)
{
    if (!connection_ || !transport_ || !collector_)
        throw proton::error("connection_engine create failed");
    pn_transport_bind(unwrap(transport_), unwrap(connection_));
    pn_connection_collect(unwrap(connection_), collector_.get());
    connection_context& ctx = connection_context::get(connection_);
    ctx.container = &container_;
    ctx.link_gen = &namer;
    ctx.event_loop.reset(loop);
}
Exemple #12
0
/* Like common_handler but does not auto-close the listener after one accept,
   and returns on LISTENER_CLOSE
*/
static pn_event_type_t listen_handler(test_handler_t *th, pn_event_t *e) {
  switch (pn_event_type(e)) {
   case PN_LISTENER_ACCEPT:
    /* No automatic listener close/free for tests that accept multiple connections */
    last_accepted = pn_connection();
    pn_listener_accept2(pn_event_listener(e), last_accepted, NULL);
    /* No automatic close */
    return PN_EVENT_NONE;

   case PN_LISTENER_CLOSE:
    return PN_LISTENER_CLOSE;

   default:
    return common_handler(th, e);
  }
}
Exemple #13
0
static void test_netaddr(test_t *t) {
  test_proactor_t tps[] ={ test_proactor(t, open_wake_handler), test_proactor(t, listen_handler) };
  pn_proactor_t *client = tps[0].proactor;
  /* Use IPv4 to get consistent results all platforms */
  pn_listener_t *l = test_listen(&tps[1], "127.0.0.1");
  pn_connection_t *c = pn_connection();
  pn_proactor_connect2(client, c, NULL, listener_info(l).connect);
  if (!TEST_ETYPE_EQUAL(t, PN_CONNECTION_REMOTE_OPEN, TEST_PROACTORS_RUN(tps))) {
    TEST_COND_EMPTY(t, last_condition); /* Show the last condition */
    return;                     /* don't continue if connection is closed */
  }

  /* client remote, client local, server remote and server local address strings */
  char cr[1024], cl[1024], sr[1024], sl[1024];

  pn_transport_t *ct = pn_connection_transport(c);
  const pn_netaddr_t *na = pn_transport_remote_addr(ct);
  pn_netaddr_str(na, cr, sizeof(cr));
  TEST_STR_IN(t, listener_info(l).port, cr); /* remote address has listening port */

  pn_connection_t *s = last_accepted; /* server side of the connection */

  pn_transport_t *st = pn_connection_transport(s);
  if (!TEST_CHECK(t, st)) return;
  pn_netaddr_str(pn_transport_local_addr(st), sl, sizeof(sl));
  TEST_STR_EQUAL(t, cr, sl);  /* client remote == server local */

  pn_netaddr_str(pn_transport_local_addr(ct), cl, sizeof(cl));
  pn_netaddr_str(pn_transport_remote_addr(st), sr, sizeof(sr));
  TEST_STR_EQUAL(t, cl, sr);    /* client local == server remote */

  char host[MAX_STR] = "";
  char serv[MAX_STR] = "";
  int err = pn_netaddr_host_port(na, host, sizeof(host), serv, sizeof(serv));
  TEST_CHECK(t, 0 == err);
  TEST_STR_EQUAL(t, "127.0.0.1", host);
  TEST_STR_EQUAL(t, listener_info(l).port, serv);

  /* Make sure you can use NULL, 0 to get length of address string without a crash */
  size_t len = pn_netaddr_str(pn_transport_local_addr(ct), NULL, 0);
  TEST_CHECKF(t, strlen(cl) == len, "%d != %d", strlen(cl), len);

  TEST_PROACTORS_DRAIN(tps);
  TEST_PROACTORS_DESTROY(tps);
}
Exemple #14
0
/* Test sending/receiving a message in chunks */
static void test_message_stream(test_t *t) {
  test_proactor_t tps[] ={
    test_proactor(t, message_stream_handler),
    test_proactor(t, message_stream_handler)
  };
  pn_proactor_t *client = tps[0].proactor;
  pn_listener_t *l = test_listen(&tps[1], "");
  struct message_stream_context ctx = { 0 };
  tps[0].handler.context = &ctx;
  tps[1].handler.context = &ctx;

  /* Encode a large (not very) message to send in chunks */
  char *body = (char*)malloc(BODY);
  memset(body, 'x', BODY);
  pn_message_t *m = pn_message();
  pn_data_put_binary(pn_message_body(m), pn_bytes(BODY, body));
  free(body);
  ctx.size = message_encode(m, &ctx.send_buf);
  pn_message_free(m);

  pn_connection_t *c = pn_connection();
  pn_proactor_connect2(client, c, NULL, listener_info(l).connect);
  pn_session_t *ssn = pn_session(c);
  pn_session_open(ssn);
  pn_link_t *snd = pn_sender(ssn, "x");
  pn_link_open(snd);
  TEST_PROACTORS_RUN_UNTIL(tps, PN_LINK_FLOW);

  /* Send and receive the message in chunks */
  do {
    pn_connection_wake(c);      /* Initiate send/receive of one chunk */
    do {                        /* May be multiple receives for one send */
      TEST_PROACTORS_RUN_UNTIL(tps, PN_DELIVERY);
    } while (ctx.received < ctx.sent);
  } while (!ctx.complete);
  TEST_CHECK(t, ctx.received == ctx.size);
  TEST_CHECK(t, ctx.sent == ctx.size);
  TEST_CHECK(t, !memcmp(ctx.send_buf.start, ctx.recv_buf.start, ctx.size));

  free(ctx.send_buf.start);
  free(ctx.recv_buf.start);
  TEST_PROACTORS_DESTROY(tps);
}
Exemple #15
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;
}
Exemple #16
0
bool
get_sasl_over_with ( pn_connector_t * connector )
{
  pn_sasl_t *sasl = pn_connector_sasl ( connector );

  while ( pn_sasl_state(sasl) != PN_SASL_PASS ) 
  {
    switch ( pn_sasl_state(sasl)) 
    {
      case PN_SASL_IDLE:
        return false;
      break;

      case PN_SASL_CONF:
        pn_sasl_mechanisms(sasl, "PLAIN ANONYMOUS");
        pn_sasl_server(sasl);
      break;

      case PN_SASL_STEP:
      {
        char response [ MY_BUF_SIZE ];
        pn_sasl_recv(sasl, response, pn_sasl_pending(sasl) );
        pn_sasl_done(sasl, PN_SASL_OK);
        pn_connector_set_connection(connector, pn_connection());
      }
      break;

      case PN_SASL_PASS:
      break;

      case PN_SASL_FAIL:
        return false;
      break;
    }
  }
  
  return true;
}
Exemple #17
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);
  }
}
Exemple #18
0
int main(int argc, char **argv)
{
  char *url = NULL;
  char *address = "queue";
  char *mechanism = "ANONYMOUS";
  int count = 1;
  bool quiet = false;
  int high = 100;
  int low = 50;
  int size = 32;

  int opt;
  while ((opt = getopt(argc, argv, "c:a:m:n:s:u:l:qhVXY")) != -1)
  {
    switch (opt) {
    case 'c':
      if (url) pn_fatal("multiple connect urls not allowed\n");
      url = optarg;
      break;
    case 'a':
      address = optarg;
      break;
    case 'm':
      mechanism = optarg;
      break;
    case 'n':
      count = atoi(optarg);
      break;
    case 's':
      size = atoi(optarg);
      break;
    case 'u':
      high = atoi(optarg);
      break;
    case 'l':
      low = atoi(optarg);
      break;
    case 'q':
      quiet = true;
      break;
    case 'V':
      printf("proton version %i.%i\n", PN_VERSION_MAJOR, PN_VERSION_MINOR);
      exit(EXIT_SUCCESS);
    case 'X':
      value(argc, argv);
      exit(EXIT_SUCCESS);
    case 'Y':
      buffer(argc, argv);
      exit(EXIT_SUCCESS);
    case 'h':
      printf("Usage: %s [-h] [-c [user[:password]@]host[:port]] [-a <address>] [-m <sasl-mech>]\n", argv[0]);
      printf("\n");
      printf("    -c    The connect url.\n");
      printf("    -a    The AMQP address.\n");
      printf("    -m    The SASL mechanism.\n");
      printf("    -n    The number of messages.\n");
      printf("    -s    Message size.\n");
      printf("    -u    Upper flow threshold.\n");
      printf("    -l    Lower flow threshold.\n");
      printf("    -q    Supress printouts.\n");
      printf("    -h    Print this help.\n");
      exit(EXIT_SUCCESS);
    default: /* '?' */
      pn_fatal("Usage: %s -h\n", argv[0]);
    }
  }

  char *user = NULL;
  char *pass = NULL;
  char *host = "0.0.0.0";
  char *port = "5672";

  parse_url(url, &user, &pass, &host, &port);

  pn_driver_t *drv = pn_driver();
  if (url) {
    struct client_context ctx = {false, false, count, count, drv, quiet, size, high, low};
    ctx.username = user;
    ctx.password = pass;
    ctx.mechanism = mechanism;
    ctx.hostname = host;
    ctx.address = address;
    pn_connector_t *ctor = pn_connector(drv, host, port, &ctx);
    if (!ctor) pn_fatal("connector failed\n");
    pn_connector_set_connection(ctor, pn_connection());
    while (!ctx.done) {
      pn_driver_wait(drv, -1);
      pn_connector_t *c;
      while ((c = pn_driver_connector(drv))) {
        pn_connector_process(c);
        client_callback(c);
        if (pn_connector_closed(c)) {
	  pn_connection_free(pn_connector_connection(c));
          pn_connector_free(c);
        } else {
          pn_connector_process(c);
        }
      }
    }
  } else {
    struct server_context ctx = {0, quiet, size};
    if (!pn_listener(drv, host, port, &ctx)) pn_fatal("listener failed\n");
    while (true) {
      pn_driver_wait(drv, -1);
      pn_listener_t *l;
      pn_connector_t *c;

      while ((l = pn_driver_listener(drv))) {
        c = pn_listener_accept(l);
        pn_connector_set_context(c, &ctx);
      }

      while ((c = pn_driver_connector(drv))) {
        pn_connector_process(c);
        server_callback(c);
        if (pn_connector_closed(c)) {
	  pn_connection_free(pn_connector_connection(c));
          pn_connector_free(c);
        } else {
          pn_connector_process(c);
        }
      }
    }
  }

  pn_driver_free(drv);

  return 0;
}