void connection_engine::try_read() {
    size_t max = can_read();
    if (max == 0) return;
    try {
        size_t n = io_read(pn_transport_tail(ctx_->transport), max);
        if (n > max)
            throw io_error(msg() << "read invalid size: " << n << " > " << max);
        pn_transport_process(ctx_->transport, n);
    } catch (const closed_error&) {
        pn_transport_close_tail(ctx_->transport);
    } catch (const io_error& e) {
        set_error(ctx_, e.what());
        pn_transport_close_tail(ctx_->transport);
    }
}
Exemple #2
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);
  }
}
Exemple #3
0
static void pni_connection_error(pn_selectable_t *sel) {
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  pn_transport_close_head(transport);
  pn_transport_close_tail(transport);
  pn_selectable_terminate(sel);
  pn_reactor_update(reactor, sel);
}
Exemple #4
0
/* Close the transport to abort a connection, i.e. close the socket without an AMQP close */
static pn_event_type_t listen_abort_handler(test_handler_t *th, pn_event_t *e) {
  switch (pn_event_type(e)) {
   case PN_CONNECTION_REMOTE_OPEN:
    /* Close the transport - abruptly closes the socket */
    pn_transport_close_tail(pn_connection_transport(pn_event_connection(e)));
    pn_transport_close_head(pn_connection_transport(pn_event_connection(e)));
    return PN_EVENT_NONE;

   default:
    /* Don't auto-close the listener to keep the event sequences simple */
    return listen_handler(th, e);
  }
}
void connection_engine::read_close() {
    pn_transport_close_tail(unwrap(transport_));
}
Exemple #6
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);
}