int pn_selector_select(pn_selector_t *selector, int timeout) { assert(selector); pn_error_clear(selector->error); pn_timestamp_t deadline = 0; pn_timestamp_t now = pn_i_now(); if (timeout) { if (selector->deadlines_head) deadline = selector->deadlines_head->deadline; } if (deadline) { int64_t delta = deadline - now; if (delta < 0) { delta = 0; } if (timeout < 0) timeout = delta; else if (timeout > delta) timeout = delta; } deadline = (timeout >= 0) ? now + timeout : 0; // Process all currently available completions, even if matched events available pni_iocp_drain_completions(selector->iocp); pni_zombie_check(selector->iocp, now); // Loop until an interested event is matched, or until deadline while (true) { if (selector->triggered_list_head) break; if (deadline && deadline <= now) break; pn_timestamp_t completion_deadline = deadline; pn_timestamp_t zd = pni_zombie_deadline(selector->iocp); if (zd) completion_deadline = completion_deadline ? pn_min(zd, completion_deadline) : zd; int completion_timeout = (!completion_deadline) ? -1 : completion_deadline - now; int rv = pni_iocp_wait_one(selector->iocp, completion_timeout, selector->error); if (rv < 0) return pn_error_code(selector->error); now = pn_i_now(); if (zd && zd <= now) { pni_zombie_check(selector->iocp, now); } } selector->current = 0; selector->awoken = now; for (iocpdesc_t *iocpd = selector->deadlines_head; iocpd; iocpd = iocpd->deadlines_next) { if (iocpd->deadline <= now) pni_events_update(iocpd, iocpd->events | PN_EXPIRED); else break; } selector->current_triggered = selector->triggered_list_head; return pn_error_code(selector->error); }
int pn_messenger_errno(pn_messenger_t *messenger) { if (messenger) { return pn_error_code(messenger->error); } else { return PN_ARG_ERR; } }
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; } }
ssize_t pni_iocp_recv(iocpdesc_t *iocpd, void *buf, size_t size, bool *would_block, pn_error_t *error) { if (size == 0) return 0; *would_block = false; if (is_listener(iocpd)) { set_iocp_error_status(error, PN_ERR, WSAEOPNOTSUPP); return SOCKET_ERROR; } if (iocpd->closing) { // Previous call to pn_close() set_iocp_error_status(error, PN_ERR, WSAESHUTDOWN); return SOCKET_ERROR; } if (iocpd->read_closed) { if (pn_error_code(iocpd->error)) pn_error_copy(error, iocpd->error); else set_iocp_error_status(error, PN_ERR, WSAENOTCONN); return SOCKET_ERROR; } int count = recv(iocpd->socket, (char *) buf, size, 0); if (count > 0) { pni_events_update(iocpd, iocpd->events & ~PN_READABLE); begin_zero_byte_read(iocpd); return (ssize_t) count; } else if (count == 0) { iocpd->read_closed = true; return 0; } if (WSAGetLastError() == WSAEWOULDBLOCK) *would_block = true; else { set_iocp_error_status(error, PN_ERR, WSAGetLastError()); iocpd->read_closed = true; } return SOCKET_ERROR; }
int pn_scanner_errno(pn_scanner_t *scanner) { return pn_error_code(scanner->error); }