예제 #1
0
/* Test that we can control listen/select on ipv6/v4 and listen on both by default */
static void test_ipv4_ipv6(test_t *t) {
  test_proactor_t tps[] ={ test_proactor(t, open_close_handler), test_proactor(t, listen_handler) };
  pn_proactor_t *client = tps[0].proactor, *server = tps[1].proactor;

  /* Listen on all interfaces for IPv4 only. */
  pn_listener_t *l4 = test_listen(&tps[1], "0.0.0.0");
  TEST_PROACTORS_DRAIN(tps);

  /* Empty address listens on both IPv4 and IPv6 on all interfaces */
  pn_listener_t *l = test_listen(&tps[1], "");
  TEST_PROACTORS_DRAIN(tps);

#define EXPECT_CONNECT(LISTENER, HOST) do {                             \
    char addr[1024];                                                    \
    pn_proactor_addr(addr, sizeof(addr), HOST, listener_info(LISTENER).port); \
    pn_proactor_connect2(client, NULL, NULL, addr);                     \
    TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps));  \
    TEST_COND_EMPTY(t, last_condition);                                 \
    TEST_PROACTORS_DRAIN(tps);                                          \
  } while(0)

  EXPECT_CONNECT(l4, "127.0.0.1"); /* v4->v4 */
  EXPECT_CONNECT(l4, "");          /* local->v4*/

  EXPECT_CONNECT(l, "127.0.0.1"); /* v4->all */
  EXPECT_CONNECT(l, "");          /* local->all */

  /* Listen on ipv6 loopback, if it fails skip ipv6 tests.

     NOTE: Don't use the unspecified address "::" here - ipv6-disabled platforms
     may allow listening on "::" without complaining. However they won't have a
     local ipv6 loopback configured, so "::1" will force an error.
  */
  TEST_PROACTORS_DRAIN(tps);
  pn_listener_t *l6 = pn_listener();
  pn_proactor_listen(server, l6, "::1:0", 4);
  pn_event_type_t e = TEST_PROACTORS_RUN(tps);
  if (e == PN_LISTENER_OPEN && !pn_condition_is_set(last_condition)) {
    TEST_PROACTORS_DRAIN(tps);

    EXPECT_CONNECT(l6, "::1"); /* v6->v6 */
    EXPECT_CONNECT(l6, "");    /* local->v6 */
    EXPECT_CONNECT(l, "::1");  /* v6->all */

    pn_listener_close(l6);
  } else  {
    const char *d = pn_condition_get_description(last_condition);
    TEST_LOGF(t, "skip IPv6 tests: %s %s", pn_event_type_name(e), d ? d : "no condition");
  }

  pn_listener_close(l);
  pn_listener_close(l4);
  TEST_PROACTORS_DESTROY(tps);
}
예제 #2
0
/* Verify that pn_transport_close_head/tail aborts a connection without an AMQP protocol close */
static void test_refuse(test_t *t) {
  test_proactor_t tps[] = { test_proactor(t, open_close_handler), test_proactor(t, listen_refuse_handler) };
  pn_proactor_t *client = tps[0].proactor;
  pn_listener_t *l = test_listen(&tps[1], "");
  pn_proactor_connect2(client, NULL, NULL, listener_info(l).connect);

  /* client transport closes */
  TEST_ETYPE_EQUAL(t, PN_TRANSPORT_CLOSED, TEST_PROACTORS_RUN(tps)); /* client */
  TEST_COND_NAME(t, "amqp:connection:framing-error", last_condition);

  pn_listener_close(l);
  while (TEST_PROACTORS_RUN(tps) != PN_PROACTOR_INACTIVE) {}
  while (TEST_PROACTORS_RUN(tps) != PN_PROACTOR_INACTIVE) {}

  /* Verify expected event sequences, no unexpected events */
  TEST_HANDLER_EXPECT(
    &tps[0].handler,
    PN_CONNECTION_INIT, PN_CONNECTION_LOCAL_OPEN, PN_CONNECTION_BOUND,
    PN_TRANSPORT_TAIL_CLOSED, PN_TRANSPORT_ERROR, PN_TRANSPORT_HEAD_CLOSED, PN_TRANSPORT_CLOSED,
    PN_PROACTOR_INACTIVE,
    0);

  TEST_HANDLER_EXPECT(
    &tps[1].handler,
    PN_LISTENER_OPEN, PN_LISTENER_ACCEPT,
    PN_CONNECTION_INIT, PN_CONNECTION_BOUND,
    PN_TRANSPORT_TAIL_CLOSED, PN_TRANSPORT_ERROR, PN_TRANSPORT_HEAD_CLOSED, PN_TRANSPORT_CLOSED,
    PN_LISTENER_CLOSE,
    PN_PROACTOR_INACTIVE,
    0);

  TEST_PROACTORS_DESTROY(tps);
}
예제 #3
0
int pn_messenger_stop(pn_messenger_t *messenger)
{
  if (!messenger) return PN_ARG_ERR;

  for (int i = 0; i < messenger->size; i++) {
    pn_connector_t *ctor = messenger->connectors[i];
    pn_connection_t *conn = pn_connector_connection(ctor);
    pn_link_t *link = pn_link_head(conn, PN_LOCAL_ACTIVE);
    while (link) {
      pn_link_close(link);
      link = pn_link_next(link, PN_LOCAL_ACTIVE);
    }
    pn_connection_close(conn);
  }

  pn_listener_t *l = pn_listener_head(messenger->driver);
  while (l) {
    pn_listener_close(l);
    pn_listener_t *prev = l;
    l = pn_listener_next(l);
    pn_listener_free(prev);
  }

  return pn_messenger_sync(messenger, pn_messenger_stopped);
}
예제 #4
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 */
  }
}
예제 #5
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);
}
예제 #6
0
void qd_connection_manager_delete_listener(qd_dispatch_t *qd, void *impl)
{
    qd_listener_t *li = (qd_listener_t*) impl;
    if (li) {
        if (li->pn_listener) {
            pn_listener_close(li->pn_listener);
        }
        DEQ_REMOVE(qd->connection_manager->listeners, li);
        qd_listener_decref(li);
    }
}
예제 #7
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);
}