std::string Connection::getError() { std::stringstream text; pn_error_t* cerror = pn_connection_error(connection); if (cerror) text << "connection error " << pn_error_text(cerror) << " [" << cerror << "]"; pn_error_t* terror = pn_transport_error(transport); if (terror) text << "transport error " << pn_error_text(terror) << " [" << terror << "]"; return text.str(); }
std::string ConnectionContext::getError() { std::stringstream text; pn_error_t* cerror = pn_connection_error(connection); if (cerror) text << "connection error " << pn_error_text(cerror); pn_error_t* terror = pn_transport_error(engine); if (terror) text << "transport error " << pn_error_text(terror); return text.str(); }
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); } }
void protonError(int err, char *step, pn_messenger_t *messenger) { const char *errMsg = NULL; if (0 == err) { return; } printf("ERROR: PROTON API: %s Errno: %d (%s)\n", step, err, pn_code(err)); #if (PN_VERSION_MINOR == 4) /* ** Proton-C 0.4 returns an error message directly */ errMsg = pn_messenger_error(messenger); if (NULL == errMsg) { errMsg = "pn_messenger_error() returned NULL"; } #else /* ** Proton-C 0.5 and later returns an error structure which ** you retrieve the error message from as a separate step. */ { pn_error_t *errInfo = pn_messenger_error(messenger); errMsg = pn_error_text(errInfo); } #endif printf("ERROR: PROTON Msg: %s\n", (NULL == errMsg) ? "NULL" : errMsg); }
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); } }
pn_socket_t pni_iocp_end_accept(iocpdesc_t *ld, sockaddr *addr, socklen_t *addrlen, bool *would_block, pn_error_t *error) { if (!is_listener(ld)) { set_iocp_error_status(error, PN_ERR, WSAEOPNOTSUPP); return INVALID_SOCKET; } if (ld->read_closed) { set_iocp_error_status(error, PN_ERR, WSAENOTSOCK); return INVALID_SOCKET; } if (pn_list_size(ld->acceptor->accepts) == 0) { if (ld->events & PN_READABLE && ld->iocp->iocp_trace) iocp_log("listen socket readable with no available accept completions\n"); *would_block = true; return INVALID_SOCKET; } accept_result_t *result = (accept_result_t *) pn_list_get(ld->acceptor->accepts, 0); pn_list_del(ld->acceptor->accepts, 0, 1); if (!pn_list_size(ld->acceptor->accepts)) pni_events_update(ld, ld->events & ~PN_READABLE); // No pending accepts pn_socket_t accept_sock; if (result->base.status) { accept_sock = INVALID_SOCKET; pni_win32_error(ld->error, "accept failure", result->base.status); if (ld->iocp->iocp_trace) iocp_log("%s\n", pn_error_text(ld->error)); // App never sees this socket so close it here. pni_iocp_begin_close(result->new_sock); } else { accept_sock = result->new_sock->socket; // AcceptEx special setsockopt: setsockopt(accept_sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&ld->socket, sizeof (SOCKET)); if (addr && addrlen && *addrlen > 0) { sockaddr_storage *local_addr = NULL; sockaddr_storage *remote_addr = NULL; int local_addrlen, remote_addrlen; LPFN_GETACCEPTEXSOCKADDRS fn = ld->acceptor->fn_get_accept_ex_sockaddrs; fn(result->address_buffer, 0, IOCP_SOCKADDRMAXLEN, IOCP_SOCKADDRMAXLEN, (SOCKADDR **) &local_addr, &local_addrlen, (SOCKADDR **) &remote_addr, &remote_addrlen); *addrlen = pn_min(*addrlen, remote_addrlen); memmove(addr, remote_addr, *addrlen); } } if (accept_sock != INVALID_SOCKET) { // Connected. result->new_sock->read_closed = false; result->new_sock->write_closed = false; } // Done with the completion result, so reuse it result->new_sock = NULL; begin_accept(ld->acceptor, result); return accept_sock; }
const char *pn_messenger_error(pn_messenger_t *messenger) { if (messenger) { return pn_error_text(messenger->error); } else { return NULL; } }
ssize_t pni_iocp_begin_write(iocpdesc_t *iocpd, const void *buf, size_t len, bool *would_block, pn_error_t *error) { if (len == 0) return 0; *would_block = false; if (is_listener(iocpd)) { set_iocp_error_status(error, PN_ERR, WSAEOPNOTSUPP); return INVALID_SOCKET; } if (iocpd->closing) { set_iocp_error_status(error, PN_ERR, WSAESHUTDOWN); return SOCKET_ERROR; } if (iocpd->write_closed) { assert(pn_error_code(iocpd->error)); pn_error_copy(error, iocpd->error); if (iocpd->iocp->iocp_trace) iocp_log("write error: %s\n", pn_error_text(error)); return SOCKET_ERROR; } if (len == 0) return 0; if (!(iocpd->events & PN_WRITABLE)) { *would_block = true; return SOCKET_ERROR; } size_t written = 0; size_t requested = len; const char *outgoing = (const char *) buf; size_t available = pni_write_pipeline_reserve(iocpd->pipeline, len); if (!available) { *would_block = true; return SOCKET_ERROR; } for (size_t wr_count = 0; wr_count < available; wr_count++) { write_result_t *result = pni_write_pipeline_next(iocpd->pipeline); assert(result); result->base.iocpd = iocpd; ssize_t actual_len = pn_min(len, result->buffer.size); result->requested = actual_len; memmove((void *)result->buffer.start, outgoing, actual_len); outgoing += actual_len; written += actual_len; len -= actual_len; int werror = submit_write(result, result->buffer.start, actual_len); if (werror && WSAGetLastError() != ERROR_IO_PENDING) { pni_write_pipeline_return(iocpd->pipeline, result); iocpdesc_fail(iocpd, WSAGetLastError(), "overlapped send"); return SOCKET_ERROR; } iocpd->ops_in_progress++; } if (!pni_write_pipeline_writable(iocpd->pipeline)) pni_events_update(iocpd, iocpd->events & ~PN_WRITABLE); return written; }
int pn_error_copy(pn_error_t *error, pn_error_t *src) { assert(error); if (src) { return pn_error_set(error, pn_error_code(src), pn_error_text(src)); } else { pn_error_clear(error); return 0; } }
static void iocpdesc_fail(iocpdesc_t *iocpd, HRESULT status, const char* text) { pni_win32_error(iocpd->error, text, status); if (iocpd->iocp->iocp_trace) { iocp_log("connection terminated: %s\n", pn_error_text(iocpd->error)); } iocpd->write_closed = true; iocpd->read_closed = true; iocpd->poll_error = true; pni_events_update(iocpd, iocpd->events & ~(PN_READABLE | PN_WRITABLE)); }
int pn_post_frame(pn_dispatcher_t *disp, uint16_t ch, const char *fmt, ...) { va_list ap; va_start(ap, fmt); pn_data_clear(disp->output_args); int err = pn_data_vfill(disp->output_args, fmt, ap); va_end(ap); if (err) { pn_transport_logf(disp->transport, "error posting frame: %s, %s: %s", fmt, pn_code(err), pn_error_text(pn_data_error(disp->output_args))); return PN_ERR; } pn_do_trace(disp, ch, OUT, disp->output_args, disp->output_payload, disp->output_size); encode_performatives: pn_buffer_clear( disp->frame ); pn_bytes_t buf = pn_buffer_bytes( disp->frame ); buf.size = pn_buffer_available( disp->frame ); ssize_t wr = pn_data_encode( disp->output_args, buf.start, buf.size ); if (wr < 0) { if (wr == PN_OVERFLOW) { pn_buffer_ensure( disp->frame, pn_buffer_available( disp->frame ) * 2 ); goto encode_performatives; } pn_transport_logf(disp->transport, "error posting frame: %s", pn_code(wr)); return PN_ERR; } pn_frame_t frame = {disp->frame_type}; frame.channel = ch; frame.payload = buf.start; frame.size = wr; size_t n; while (!(n = pn_write_frame(disp->output + disp->available, disp->capacity - disp->available, frame))) { disp->capacity *= 2; disp->output = (char *) realloc(disp->output, disp->capacity); } disp->output_frames_ct += 1; if (disp->trace & PN_TRACE_RAW) { pn_string_set(disp->scratch, "RAW: \""); pn_quote(disp->scratch, disp->output + disp->available, n); pn_string_addf(disp->scratch, "\""); pn_transport_log(disp->transport, pn_string_get(disp->scratch)); } disp->available += n; return 0; }
pn_socket_t pni_iocp_begin_connect(iocp_t *iocp, pn_socket_t sock, struct addrinfo *addr, pn_error_t *error) { // addr lives for the duration of the async connect. Caller has passed ownership here. // See connect_result_finalize(). // Use of Windows-specific ConnectEx() requires our socket to be "loosely" pre-bound: sockaddr_storage sa; memset(&sa, 0, sizeof(sa)); sa.ss_family = addr->ai_family; if (bind(sock, (SOCKADDR *) &sa, addr->ai_addrlen)) { pni_win32_error(error, "begin async connection", WSAGetLastError()); if (iocp->iocp_trace) iocp_log("%s\n", pn_error_text(error)); closesocket(sock); freeaddrinfo(addr); return INVALID_SOCKET; } iocpdesc_t *iocpd = pni_iocpdesc_create(iocp, sock, false); bind_to_completion_port(iocpd); LPFN_CONNECTEX fn_connect_ex = lookup_connect_ex(iocpd->socket); connect_result_t *result = connect_result(iocpd, addr); DWORD unused; bool success = fn_connect_ex(iocpd->socket, result->addrinfo->ai_addr, result->addrinfo->ai_addrlen, NULL, 0, &unused, (LPOVERLAPPED) result); if (!success && WSAGetLastError() != ERROR_IO_PENDING) { pni_win32_error(error, "ConnectEx failure", WSAGetLastError()); pn_free(result); iocpd->write_closed = true; iocpd->read_closed = true; pni_iocp_begin_close(iocpd); sock = INVALID_SOCKET; if (iocp->iocp_trace) iocp_log("%s\n", pn_error_text(error)); } else { iocpd->ops_in_progress++; } return sock; }
int pn_dispatch_frame(pn_dispatcher_t *disp, pn_frame_t frame) { if (frame.size == 0) { // ignore null frames if (disp->trace & PN_TRACE_FRM) pn_transport_logf(disp->transport, "%u <- (EMPTY FRAME)\n", frame.channel); return 0; } ssize_t dsize = pn_data_decode(disp->args, frame.payload, frame.size); if (dsize < 0) { pn_string_format(disp->scratch, "Error decoding frame: %s %s\n", pn_code(dsize), pn_error_text(pn_data_error(disp->args))); pn_quote(disp->scratch, frame.payload, frame.size); pn_transport_log(disp->transport, pn_string_get(disp->scratch)); return dsize; } disp->channel = frame.channel; // XXX: assuming numeric uint64_t lcode; bool scanned; int e = pn_data_scan(disp->args, "D?L.", &scanned, &lcode); if (e) { pn_transport_log(disp->transport, "Scan error"); return e; } if (!scanned) { pn_transport_log(disp->transport, "Error dispatching frame"); return PN_ERR; } uint8_t code = lcode; disp->code = code; disp->size = frame.size - dsize; if (disp->size) disp->payload = frame.payload + dsize; pn_do_trace(disp, disp->channel, IN, disp->args, disp->payload, disp->size); pn_action_t *action = disp->actions[code]; int err = action(disp); disp->channel = 0; disp->code = 0; pn_data_clear(disp->args); disp->size = 0; disp->payload = NULL; return err; }
void pn_io_initialize(void *obj) { pn_io_t *io = (pn_io_t *) obj; io->error = pn_error(); io->wouldblock = false; io->trace = pn_env_bool("PN_TRACE_DRV"); /* Request WinSock 2.2 */ WORD wsa_ver = MAKEWORD(2, 2); WSADATA unused; int err = WSAStartup(wsa_ver, &unused); if (err) { pni_win32_error(io->error, "WSAStartup", WSAGetLastError()); fprintf(stderr, "Can't load WinSock: %s\n", pn_error_text(io->error)); } io->iocp = pni_iocp(); }
int pn_post_transfer_frame(pn_dispatcher_t *disp, uint16_t ch, uint32_t handle, pn_sequence_t id, const pn_bytes_t *tag, uint32_t message_format, bool settled, bool more, pn_sequence_t frame_limit) { bool more_flag = more; int framecount = 0; // create preformatives, assuming 'more' flag need not change compute_performatives: pn_data_clear(disp->output_args); int err = pn_data_fill(disp->output_args, "DL[IIzIoo]", TRANSFER, handle, id, tag->size, tag->start, message_format, settled, more_flag); if (err) { pn_transport_logf(disp->transport, "error posting transfer frame: %s: %s", pn_code(err), pn_error_text(pn_data_error(disp->output_args))); return PN_ERR; } do { // send as many frames as possible without changing the 'more' flag... encode_performatives: pn_buffer_clear( disp->frame ); pn_bytes_t buf = pn_buffer_bytes( disp->frame ); buf.size = pn_buffer_available( disp->frame ); ssize_t wr = pn_data_encode(disp->output_args, buf.start, buf.size); if (wr < 0) { if (wr == PN_OVERFLOW) { pn_buffer_ensure( disp->frame, pn_buffer_available( disp->frame ) * 2 ); goto encode_performatives; } pn_transport_logf(disp->transport, "error posting frame: %s", pn_code(wr)); return PN_ERR; } buf.size = wr; // check if we need to break up the outbound frame size_t available = disp->output_size; if (disp->remote_max_frame) { if ((available + buf.size) > disp->remote_max_frame - 8) { available = disp->remote_max_frame - 8 - buf.size; if (more_flag == false) { more_flag = true; goto compute_performatives; // deal with flag change } } else if (more_flag == true && more == false) { // caller has no more, and this is the last frame more_flag = false; goto compute_performatives; } } if (pn_buffer_available( disp->frame ) < (available + buf.size)) { // not enough room for payload - try again... pn_buffer_ensure( disp->frame, available + buf.size ); goto encode_performatives; } pn_do_trace(disp, ch, OUT, disp->output_args, disp->output_payload, available); memmove( buf.start + buf.size, disp->output_payload, available); disp->output_payload += available; disp->output_size -= available; buf.size += available; pn_frame_t frame = {disp->frame_type}; frame.channel = ch; frame.payload = buf.start; frame.size = buf.size; size_t n; while (!(n = pn_write_frame(disp->output + disp->available, disp->capacity - disp->available, frame))) { disp->capacity *= 2; disp->output = (char *) realloc(disp->output, disp->capacity); } disp->output_frames_ct += 1; framecount++; if (disp->trace & PN_TRACE_RAW) { pn_string_set(disp->scratch, "RAW: \""); pn_quote(disp->scratch, disp->output + disp->available, n); pn_string_addf(disp->scratch, "\""); pn_transport_log(disp->transport, pn_string_get(disp->scratch)); } disp->available += n; } while (disp->output_size > 0 && framecount < frame_limit); disp->output_payload = NULL; return framecount; }
const char *pn_scanner_error(pn_scanner_t *scanner) { return pn_error_text(scanner->error); }
void amqp::Sender::_throwError() { throw std::exception(pn_error_text(pn_messenger_error(m_messenger))); }
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); }