src/ssl_sock.c
static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
{
	int ret, done = 0;
	int try = count;

	if (!conn->xprt_ctx)
		goto out_error;

	if (conn->flags & CO_FL_HANDSHAKE)
		/* a handshake was requested */
		return 0;

	/* compute the maximum block size we can read at once. */
	if (buffer_empty(buf)) {
		/* let's realign the buffer to optimize I/O */
		buf->p = buf->data;
	}
	else if (buf->data + buf->o < buf->p &&
		 buf->p + buf->i < buf->data + buf->size) {
		/* remaining space wraps at the end, with a moving limit */
		if (try > buf->data + buf->size - (buf->p + buf->i))
			try = buf->data + buf->size - (buf->p + buf->i);
	}

	/* read the largest possible block. For this, we perform only one call
	 * to recv() unless the buffer wraps and we exactly fill the first hunk,
	 * in which case we accept to do it once again. A new attempt is made on
	 * EINTR too.
	 */
	while (try) {
		ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
		if (conn->flags & CO_FL_ERROR) {
			/* CO_FL_ERROR may be set by ssl_sock_infocbk */
			goto out_error;
		}
		if (ret > 0) {
			buf->i += ret;
			done += ret;
			if (ret < try)
				break;
			count -= ret;
			try = count;
		}
		else if (ret == 0) {
			ret =  SSL_get_error(conn->xprt_ctx, ret);
			if (ret != SSL_ERROR_ZERO_RETURN) {
				/* error on protocol or underlying transport */
				if ((ret != SSL_ERROR_SYSCALL)
				     || (errno && (errno != EAGAIN)))
					conn->flags |= CO_FL_ERROR;

				/* Clear openssl global errors stack */
				ERR_clear_error();
			}
			goto read0;
		}
		else {
			ret =  SSL_get_error(conn->xprt_ctx, ret);
			if (ret == SSL_ERROR_WANT_WRITE) {
				/* handshake is running, and it needs to enable write */
				conn->flags |= CO_FL_SSL_WAIT_HS;
				__conn_sock_want_send(conn);
				break;
			}
			else if (ret == SSL_ERROR_WANT_READ) {
				if (SSL_renegotiate_pending(conn->xprt_ctx)) {
					/* handshake is running, and it may need to re-enable read */
					conn->flags |= CO_FL_SSL_WAIT_HS;
					__conn_sock_want_recv(conn);
					break;
				}
				/* we need to poll for retry a read later */
				__conn_data_poll_recv(conn);
				break;
			}
			/* otherwise it's a real error */
			goto out_error;
		}
	}
	return done;

 read0:
	conn_sock_read0(conn);
	return done;
 out_error:
	/* Clear openssl global errors stack */
	ERR_clear_error();

	conn->flags |= CO_FL_ERROR;
	return done;
}
/* Receive up to <count> bytes from connection <conn>'s socket and store them
 * into buffer <buf>. The caller must ensure that <count> is always smaller
 * than the buffer's size. Only one call to recv() is performed, unless the
 * buffer wraps, in which case a second call may be performed. The connection's
 * flags are updated with whatever special event is detected (error, read0,
 * empty). The caller is responsible for taking care of those events and
 * avoiding the call if inappropriate. The function does not call the
 * connection's polling update function, so the caller is responsible for this.
 */
Receive up to  bytes from connection 's socket and store them
into buffer . The caller must ensure that  is always smaller
than the buffer's size. Only one call to recv() is performed, unless the
buffer wraps, in which case a second call may be performed. The connection's
flags are updated with whatever special event is detected (error, read0,
empty). The caller is responsible for taking care of those events and
avoiding the call if inappropriate. The function does not call the
connection's polling update function, so the caller is responsible for this.
Receive up to bytes from connection ' s socket and store them into buffer . The caller must ensure that is always smaller than the buffer ' s size . Only one call to recv () is performed unless the buffer wraps in which case a second call may be performed . The connection ' s flags are updated with whatever special event is detected ( error read0 empty ) . The caller is responsible for taking care of those events and avoiding the call if inappropriate . The function does not call the connection ' s polling update function so the caller is responsible for this .
static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int count)
{
	int ret, done = 0;
	int try = count;
	if (!conn->xprt_ctx)
		goto out_error;
	if (conn->flags & CO_FL_HANDSHAKE)
		return 0;
	if (buffer_empty(buf)) {
		buf->p = buf->data;
	}
	else if (buf->data + buf->o < buf->p &&
		 buf->p + buf->i < buf->data + buf->size) {
		if (try > buf->data + buf->size - (buf->p + buf->i))
			try = buf->data + buf->size - (buf->p + buf->i);
	}
	while (try) {
		ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
		if (conn->flags & CO_FL_ERROR) {
			goto out_error;
		}
		if (ret > 0) {
			buf->i += ret;
			done += ret;
			if (ret < try)
				break;
			count -= ret;
			try = count;
		}
		else if (ret == 0) {
			ret =  SSL_get_error(conn->xprt_ctx, ret);
			if (ret != SSL_ERROR_ZERO_RETURN) {
				if ((ret != SSL_ERROR_SYSCALL)
				     || (errno && (errno != EAGAIN)))
					conn->flags |= CO_FL_ERROR;
				ERR_clear_error();
			}
			goto read0;
		}
		else {
			ret =  SSL_get_error(conn->xprt_ctx, ret);
			if (ret == SSL_ERROR_WANT_WRITE) {
				conn->flags |= CO_FL_SSL_WAIT_HS;
				__conn_sock_want_send(conn);
				break;
			}
			else if (ret == SSL_ERROR_WANT_READ) {
				if (SSL_renegotiate_pending(conn->xprt_ctx)) {
					conn->flags |= CO_FL_SSL_WAIT_HS;
					__conn_sock_want_recv(conn);
					break;
				}
				__conn_data_poll_recv(conn);
				break;
			}
			goto out_error;
		}
	}
	return done;
 read0:
	conn_sock_read0(conn);
	return done;
 out_error:
	ERR_clear_error();
	conn->flags |= CO_FL_ERROR;
	return done;
}
static int ssl_sock_to_buf ( struct connection * conn , struct buffer * buf , int count ) { int ret , done = 0 ; int try = count ; if ( ! conn -> xprt_ctx ) goto out_error ; if ( conn -> flags & CO_FL_HANDSHAKE ) return 0 ; if ( buffer_empty ( buf ) ) { buf -> p = buf -> data ; } else if ( buf -> data + buf -> o < buf -> p && buf -> p + buf -> i < buf -> data + buf -> size ) { if ( try > buf -> data + buf -> size - ( buf -> p + buf -> i ) ) try = buf -> data + buf -> size - ( buf -> p + buf -> i ) ; } while ( try ) { ret = SSL_read ( conn -> xprt_ctx , bi_end ( buf ) , try ) ; if ( conn -> flags & CO_FL_ERROR ) { goto out_error ; } if ( ret > 0 ) { buf -> i += ret ; done += ret ; if ( ret < try ) break ; count -= ret ; try = count ; } else if ( ret == 0 ) { ret = SSL_get_error ( conn -> xprt_ctx , ret ) ; if ( ret != SSL_ERROR_ZERO_RETURN ) { if ( ( ret != SSL_ERROR_SYSCALL ) || ( errno && ( errno != EAGAIN ) ) ) conn -> flags |= CO_FL_ERROR ; ERR_clear_error ( ) ; } goto read0 ; } else { ret = SSL_get_error ( conn -> xprt_ctx , ret ) ; if ( ret == SSL_ERROR_WANT_WRITE ) { conn -> flags |= CO_FL_SSL_WAIT_HS ; __conn_sock_want_send ( conn ) ; break ; } else if ( ret == SSL_ERROR_WANT_READ ) { if ( SSL_renegotiate_pending ( conn -> xprt_ctx ) ) { conn -> flags |= CO_FL_SSL_WAIT_HS ; __conn_sock_want_recv ( conn ) ; break ; } __conn_data_poll_recv ( conn ) ; break ; } goto out_error ; } } return done ; read0 : conn_sock_read0 ( conn ) ; return done ; out_error : ERR_clear_error ( ) ; conn -> flags |= CO_FL_ERROR ; return done ; }
Receive up to <count> bytes from connection <conn>'s socket and store them
 into buffer <buf>.
Receive up to <count > bytes from connection <conn > ' s socket and store them into buffer <buf > .
/* a handshake was requested */ /* compute the maximum block size we can read at once. */ /* let's realign the buffer to optimize I/O */ /* remaining space wraps at the end, with a moving limit */ /* read the largest possible block. For this, we perform only one call
	 * to recv() unless the buffer wraps and we exactly fill the first hunk,
	 * in which case we accept to do it once again. A new attempt is made on
	 * EINTR too.
	 */ /* CO_FL_ERROR may be set by ssl_sock_infocbk */ /* error on protocol or underlying transport */ /* Clear openssl global errors stack */ /* handshake is running, and it needs to enable write */ /* handshake is running, and it may need to re-enable read */ /* we need to poll for retry a read later */ /* otherwise it's a real error */ /* Clear openssl global errors stack */