Example #1
0
size_t socket_read(struct client_ctx *cc, char *buf, size_t len)
{
	if (!cc->ssl)
		return socket_read_plain(cc, buf, len);

	char *bufp = buf;
	char packet[PACKET_SIZE];
	size_t packetsize = 0;

	while ((size_t) (bufp - buf) < len && (packetsize = SSL_read(cc->ssl, packet, PACKET_SIZE)) > 0){
		memcpy(bufp, packet, packetsize);
		bufp += packetsize;
	}

	return bufp - buf;
}
Example #2
0
void ListenerIO_AttemptRecv(listener *l, int available) {
    /*   --> failure --> set 'closed' error on socket, don't die */
    struct bus *b = l->bus;
    int read_from = 0;
    BUS_LOG(b, 3, LOG_LISTENER, "attempting receive", b->udata);

    for (int i = 0; i < l->tracked_fds; i++) {
        if (read_from == available) {
            break;
        }
        struct pollfd *fd = &l->fds[i + INCOMING_MSG_PIPE];
        connection_info *ci = l->fd_info[i];
        BUS_ASSERT(b, b->udata, ci->fd == fd->fd);

        BUS_LOG_SNPRINTF(b, 1, LOG_LISTENER, b->udata, 64,
                         "poll: l->fds[%d]->revents: 0x%04x",  // NOCOMMIT
                         i + INCOMING_MSG_PIPE, fd->revents);

        /* If a socket is about to be shut down, we want to get a
         * complete read from it if possible, because it's likely to be
         * an UNSOLICITEDSTATUS message with a reason for the hangup.
         * Only do single reads otherwise, though, otherwise the
         * listener can end up blocking too long handling consecutive
         * reads on a busy connection and causing the incoming command
         * queue to get backed up. */
        bool is_closing = fd->events & (POLLERR | POLLNVAL | POLLHUP);

        if (fd->revents & POLLIN) {
            // Try to read what we can (possibly before hangup)
            ssize_t cur_read = 0;
            size_t to_read = ci->to_read_size;
            do {
                BUS_LOG_SNPRINTF(b, 3, LOG_LISTENER, b->udata, 64,
                                 "reading %zd bytes from socket (buf is %zd)",
                                 ci->to_read_size, l->read_buf_size);
                BUS_ASSERT(b, b->udata, l->read_buf_size >= to_read);

                switch (ci->type) {
                case BUS_SOCKET_PLAIN:
                    cur_read = socket_read_plain(b, l, i, ci);
                    break;
                case BUS_SOCKET_SSL:
                    cur_read = socket_read_ssl(b, l, i, ci);
                    break;
                default:
                    BUS_ASSERT(b, b->udata, false);
                }
                // -1: socket error
                // 0: no more to read
            } while (is_closing && cur_read > 0 && ci->to_read_size > 0);
            read_from++;
        }

        if (fd->revents & (POLLERR | POLLNVAL)) {
            read_from++;
            BUS_LOG(b, 2, LOG_LISTENER,
                    "pollfd: socket error (POLLERR | POLLNVAL)", b->udata);
            set_error_for_socket(l, i, ci->fd, RX_ERROR_POLLERR);
        } else if (fd->revents & POLLHUP) {
            read_from++;
            BUS_LOG(b, 3, LOG_LISTENER, "pollfd: socket error POLLHUP",
                    b->udata);
            set_error_for_socket(l, i, ci->fd, RX_ERROR_POLLHUP);
        }
    }

    if (l->error_occured) {  // only conditionally do this to avoid wasting CPU
        /* This is done outside of the polling loop, to avoid erroneously repeat-polling
         * or skipping any individual file descriptors. */
        move_errored_active_sockets_to_end(l);
        l->error_occured = false;
    }
}