static ssize_t tls_readv(struct wrap_io *wio, iovec_t *iov, int iovcnt) { struct gnutella_socket *s = wio->ctx; ssize_t ret, done; int i; g_assert(socket_uses_tls(s)); g_assert(iovcnt > 0); done = 0; ret = 0; for (i = 0; i < iovcnt; i++) { const size_t size = iovec_len(&iov[i]); ret = tls_read(wio, iovec_base(&iov[i]), size); if ((ssize_t) -1 == ret) break; done += (size_t) ret; if (size != (size_t) ret) break; } return done > 0 ? done : ret; }
/** * Write I/O vector. * * @return amount of bytes written, or -1 on error. */ static ssize_t tx_deflate_writev(txdrv_t *tx, iovec_t *iov, int iovcnt) { struct attr *attr = tx->opaque; int sent = 0; if (tx_deflate_debugging(9)) { g_debug("TX %s: (%s) (buffer #%d, nagle %s, unflushed %zu) [%c%c]", G_STRFUNC, gnet_host_to_string(&tx->host), attr->fill_idx, (attr->flags & DF_NAGLE) ? "on" : "off", attr->unflushed, (attr->flags & DF_FLOWC) ? 'C' : '-', (attr->flags & DF_FLUSH) ? 'f' : '-'); } while (iovcnt-- > 0) { int ret; /* * If we're flow controlled or shut down, stop sending. */ if (attr->flags & (DF_FLOWC|DF_SHUTDOWN)) break; ret = deflate_add(tx, iovec_base(iov), iovec_len(iov)); if (-1 == ret) return -1; sent += ret; if (UNSIGNED(ret) < iovec_len(iov)) { /* Could not write all, flow-controlled */ break; } iov++; } if (tx_deflate_debugging(9)) { g_debug("TX %s: (%s) sent %lu bytes (buffer #%d, nagle %s, " "unflushed %zu) [%c%c]", G_STRFUNC, gnet_host_to_string(&tx->host), (ulong) sent, attr->fill_idx, (attr->flags & DF_NAGLE) ? "on" : "off", attr->unflushed, (attr->flags & DF_FLOWC) ? 'C' : '-', (attr->flags & DF_FLUSH) ? 'f' : '-'); } return sent; }
ssize_t do_writev(struct epoll_event *p_entry, int epoll_fd, const struct iovec vec[], size_t cnt, bool more) { g2_connection_t *w_entry = (g2_connection_t *)p_entry->data.ptr; ssize_t result = 0; if(!cnt) return 0; do { set_s_errno(0); result = writev(w_entry->com_socket, vec, cnt); } while(-1 == result && EINTR == s_errno); switch(result) { default: if(!more && iovec_len(vec, cnt) <= (size_t)result) { shortlock_lock(&w_entry->pts_lock); w_entry->poll_interrests &= ~((uint32_t)EPOLLOUT); if(!(w_entry->poll_interrests & EPOLLONESHOT)) { struct epoll_event t_entry; t_entry.data.u64 = p_entry->data.u64; t_entry.events = w_entry->poll_interrests; shortlock_unlock(&w_entry->pts_lock); if(0 > my_epoll_ctl(epoll_fd, EPOLL_CTL_MOD, w_entry->com_socket, &t_entry)) { logg_serrno(LOGF_DEBUG, "changing sockets Epoll-interrests"); w_entry->flags.dismissed = true; result = -1; } } else { shortlock_unlock(&w_entry->pts_lock); if(w_entry->flags.dismissed) { logg_posd(LOGF_DEVEL_OLD, "%s Ip: %p#I\tFDNum: %i\n", "Dismissed!", &w_entry->remote_host, w_entry->com_socket); result = -1; } } } break; case 0: if(iovec_len(vec, cnt)) { if(EAGAIN != s_errno) { logg_posd(LOGF_DEVEL_OLD, "%s Ip: %p#I\tFDNum: %i\n", "Dismissed!", &w_entry->remote_host, w_entry->com_socket); w_entry->flags.dismissed = true; result = -1; } else logg_devel("not ready to write\n"); } else if(!more) { shortlock_lock(&w_entry->pts_lock); w_entry->poll_interrests &= ~((uint32_t)EPOLLOUT); if(!(w_entry->poll_interrests & EPOLLONESHOT)) { struct epoll_event t_entry; t_entry.data.u64 = p_entry->data.u64; t_entry.events = w_entry->poll_interrests; shortlock_unlock(&w_entry->pts_lock); if(0 > my_epoll_ctl(epoll_fd, EPOLL_CTL_MOD, w_entry->com_socket, &t_entry)) { logg_serrno(LOGF_DEBUG, "changing sockets Epoll-interrests"); w_entry->flags.dismissed = true; result = -1; } } else { shortlock_unlock(&w_entry->pts_lock); if(w_entry->flags.dismissed) { logg_posd(LOGF_DEBUG, "%s ERRNO=%i Ip: %p#I\tFDNum: %i\n", "EOF reached!", s_errno, &w_entry->remote_host, w_entry->com_socket); result = -1; } } } break; case -1: if(EAGAIN != s_errno) logg_serrno(LOGF_DEBUG, "write"); break; } return result; }