Beispiel #1
0
static void setup_outgoing_link(qd_container_t *container, pn_link_t *pn_link)
{
    sys_mutex_lock(container->lock);
    qd_node_t  *node = 0;
    const char *source = pn_terminus_get_address(pn_link_remote_source(pn_link));
    qd_field_iterator_t *iter;
    // TODO - Extract the name from the structured source

    if (source) {
        iter   = qd_address_iterator_string(source, ITER_VIEW_NODE_ID);
        qd_hash_retrieve(container->node_map, iter, (void*) &node);
        qd_field_iterator_free(iter);
    }
    sys_mutex_unlock(container->lock);

    if (node == 0) {
        if (container->default_node)
            node = container->default_node;
        else {
            pn_condition_t *cond = pn_link_condition(pn_link);
            pn_condition_set_name(cond, "amqp:not-found");
            pn_condition_set_description(cond, "Source node does not exist");
            pn_link_close(pn_link);
            return;
        }
    }

    qd_link_t *link = new_qd_link_t();
    if (!link) {
        pn_condition_t *cond = pn_link_condition(pn_link);
        pn_condition_set_name(cond, "amqp:internal-error");
        pn_condition_set_description(cond, "Insufficient memory");
        pn_link_close(pn_link);
        return;
    }

    link->pn_sess    = pn_link_session(pn_link);
    link->pn_link    = pn_link;
    link->direction  = QD_OUTGOING;
    link->context    = 0;
    link->node       = node;

    link->remote_snd_settle_mode = pn_link_remote_snd_settle_mode(pn_link);
    link->drain_mode             = pn_link_get_drain(pn_link);
    link->close_sess_with_link   = false;

    //
    // Keep the borrowed references
    //
    pn_incref(pn_link);
    pn_incref(link->pn_sess);

    pn_link_set_context(pn_link, link);
    node->ntype->outgoing_handler(node->context, link);
}
Beispiel #2
0
void _qd_policy_deny_amqp_link(pn_link_t *link, qd_connection_t *qd_conn)
{
    pn_condition_t * cond = pn_link_condition(link);
    (void) pn_condition_set_name(       cond, RESOURCE_LIMIT_EXCEEDED);
    (void) pn_condition_set_description(cond, LINK_DISALLOWED);
    pn_link_close(link);
}
Beispiel #3
0
static void pni_connection_writable(pn_selectable_t *sel)
{
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  ssize_t pending = pn_transport_pending(transport);
  if (pending > 0) {
    ssize_t n = pn_send(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
                        pn_transport_head(transport), pending);
    if (n < 0) {
      if (!pn_wouldblock(pni_reactor_io(reactor))) {
        pn_condition_t *cond = pn_transport_condition(transport);
        if (!pn_condition_is_set(cond)) {
          pn_condition_set_name(cond, "proton:io");
          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
        }
        pn_transport_close_head(transport);
      }
    } else {
      pn_transport_pop(transport, n);
    }
  }

  ssize_t newpending = pn_transport_pending(transport);
  if (newpending != pending) {
    pni_connection_update(sel);
    pn_reactor_update(reactor, sel);
  }
}
Beispiel #4
0
static void pni_connection_readable(pn_selectable_t *sel)
{
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  ssize_t capacity = pn_transport_capacity(transport);
  if (capacity > 0) {
    ssize_t n = pn_recv(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
                        pn_transport_tail(transport), capacity);
    if (n <= 0) {
      if (n == 0 || !pn_wouldblock(pni_reactor_io(reactor))) {
        if (n < 0) {
          pn_condition_t *cond = pn_transport_condition(transport);
          pn_condition_set_name(cond, "proton:io");
          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
        }
        pn_transport_close_tail(transport);
      }
    } else {
      pn_transport_process(transport, (size_t)n);
    }
  }

  ssize_t newcap = pn_transport_capacity(transport);
  //occasionally transport events aren't generated when expected, so
  //the following hack ensures we always update the selector
  if (1 || newcap != capacity) {
    pni_connection_update(sel);
    pn_reactor_update(reactor, sel);
  }
}
Beispiel #5
0
void qd_policy_deny_amqp_session(pn_session_t *ssn, qd_connection_t *qd_conn)
{
    pn_condition_t * cond = pn_session_condition(ssn);
    (void) pn_condition_set_name(       cond, RESOURCE_LIMIT_EXCEEDED);
    (void) pn_condition_set_description(cond, SESSION_DISALLOWED);
    pn_session_close(ssn);
    qd_conn->policy_settings->denialCounts->sessionDenied++;
}
Beispiel #6
0
void qd_policy_private_deny_amqp_connection(pn_connection_t *conn, const char *cond_name, const char *cond_descr)
{
    pn_condition_t * cond = pn_connection_condition(conn);
    (void) pn_condition_set_name(       cond, cond_name);
    (void) pn_condition_set_description(cond, cond_descr);
    pn_connection_close(conn);
    // Connection denial counts are counted and logged by python code.
}
Beispiel #7
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);
}
Beispiel #8
0
void qdr_error_copy(qdr_error_t *from, pn_condition_t *to)
{
    if (from->name) {
        unsigned char *name = qd_field_iterator_copy(from->name->iterator);
        pn_condition_set_name(to, (char*) name);
        free(name);
    }

    if (from->description) {
        unsigned char *desc = qd_field_iterator_copy(from->description->iterator);
        pn_condition_set_description(to, (char*) desc);
        free(desc);
    }

    if (from->info)
        pn_data_copy(pn_condition_info(to), from->info);
}
Beispiel #9
0
void pni_handle_bound(pn_reactor_t *reactor, pn_event_t *event) {
  assert(reactor);
  assert(event);

  pn_connection_t *conn = pn_event_connection(event);
  pn_transport_t *transport = pn_event_transport(event);
  pn_record_t *record = pn_connection_attachments(conn);
  pn_url_t *url = (pn_url_t *)pn_record_get(record, PNI_CONN_PEER_ADDRESS);
  const char *host = NULL;
  const char *port = "5672";
  pn_string_t *str = NULL;

  // link the new transport to its reactor:
  pni_record_init_reactor(pn_transport_attachments(transport), reactor);

  if (pn_connection_acceptor(conn) != NULL) {
      // this connection was created by the acceptor.  There is already a
      // socket assigned to this connection.  Nothing needs to be done.
      return;
  }

  if (url) {
      host = pn_url_get_host(url);
      const char *uport = pn_url_get_port(url);
      if (uport) {
          port = uport;
      } else {
          const char *scheme = pn_url_get_scheme(url);
          if (scheme && strcmp(scheme, "amqps") == 0) {
              port = "5671";
          }
      }
      if (!pn_connection_get_user(conn)) {
          // user did not manually set auth info
          const char *user = pn_url_get_username(url);
          if (user) pn_connection_set_user(conn, user);
          const char *passwd = pn_url_get_password(url);
          if (passwd) pn_connection_set_password(conn, passwd);
      }
  } else {
      // for backward compatibility, see if the connection's hostname can be
      // used for the remote address.  See JIRA PROTON-1133
      const char *hostname = pn_connection_get_hostname(conn);
      if (hostname) {
          str = pn_string(hostname);
          char *h = pn_string_buffer(str);
          // see if a port has been included in the hostname.  This is not
          // allowed by the spec, but the old reactor interface allowed it.
          char *colon = strrchr(h, ':');
          if (colon) {
              *colon = '\0';
              port = colon + 1;
          }
          host = h;
      }
  }

  if (!host) {
      // error: no address configured
      pn_condition_t *cond = pn_transport_condition(transport);
      pn_condition_set_name(cond, "proton:io");
      pn_condition_set_description(cond, "Connection failed: no address configured");
      pn_transport_close_tail(transport);
      pn_transport_close_head(transport);
  } else {
      pn_socket_t sock = pn_connect(pni_reactor_io(reactor), host, port);
      // invalid sockets are ignored by poll, so we need to do this manually
      if (sock == PN_INVALID_SOCKET) {
          pn_condition_t *cond = pn_transport_condition(transport);
          pn_condition_set_name(cond, "proton:io");
          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
          pn_transport_close_tail(transport);
          pn_transport_close_head(transport);
      } else {
          pn_reactor_selectable_transport(reactor, sock, transport);
      }
  }
  pn_free(str);
}