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); } }
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); } }
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); }
/* 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_)); }
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); }