[gnutls-devel] [PATCH] Broke apart _gnutls_recv_int() to the packet and non-packet cases.
Jaak Ristioja
jaak.ristioja at cyber.ee
Mon Mar 21 11:41:54 CET 2016
Postponed, rejected or forgotten?
On 15.02.2016 12:14, Jaak Ristioja wrote:
> Only gnutls_record_recv_packet() called _gnutls_recv_int() with
> (packet != NULL). I refactored this logic directly downstream into
> gnutls_record_recv_packet(). The _gnutls_recv_int() function now only
> handles non-packet specific logic. The _gnutls_recv_int2() function
> was created to deduplicate common code which would otherwise have
> ended up in both functions.
>
> The rationale behind this change is to optimize what were previously
> calls of _gnutls_recv_int(). First of all _gnutls_recv_int() now has
> only 6 parameters, which according to the x86_64 System V Application
> Binary Interface should now fit into CPU registers and no longer use
> the stack. Secondly this change avoids a number of branching checks
> for both packet and non-packet cases.
> ---
> lib/ext/heartbeat.c | 2 +-
> lib/handshake.c | 2 +-
> lib/record.c | 103 ++++++++++++++++++++++++++++++----------------------
> lib/record.h | 1 -
> 4 files changed, 62 insertions(+), 46 deletions(-)
>
> diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c
> index cc13508..77d990b 100644
> --- a/lib/ext/heartbeat.c
> +++ b/lib/ext/heartbeat.c
> @@ -229,7 +229,7 @@ gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size,
>
> case SHB_RECV:
> ret =
> - _gnutls_recv_int(session, GNUTLS_HEARTBEAT, NULL,
> + _gnutls_recv_int(session, GNUTLS_HEARTBEAT,
> NULL, 0, NULL,
> session->internals.
> hb_actual_retrans_timeout_ms);
> diff --git a/lib/handshake.c b/lib/handshake.c
> index 3d7a153..82f605b 100644
> --- a/lib/handshake.c
> +++ b/lib/handshake.c
> @@ -3104,7 +3104,7 @@ static int recv_handshake_final(gnutls_session_t session, int init)
>
> ret =
> _gnutls_recv_int(session, GNUTLS_CHANGE_CIPHER_SPEC,
> - NULL, ccs, ccs_len, NULL, tleft);
> + ccs, ccs_len, NULL, tleft);
> if (ret <= 0) {
> ERR("recv ChangeCipherSpec", ret);
> gnutls_assert();
> diff --git a/lib/record.c b/lib/record.c
> index a2f8637..713dd94 100644
> --- a/lib/record.c
> +++ b/lib/record.c
> @@ -301,7 +301,7 @@ int gnutls_bye(gnutls_session_t session, gnutls_close_request_t how)
> do {
> ret =
> _gnutls_recv_int(session, GNUTLS_ALERT,
> - NULL, NULL, 0, NULL,
> + NULL, 0, NULL,
> session->internals.
> record_timeout_ms);
> }
> @@ -1356,23 +1356,13 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
> return ret;
> }
>
> -/* This function behaves exactly like read(). The only difference is
> - * that it accepts the gnutls_session_t and the content_type_t of data to
> - * receive (if called by the user the Content is Userdata only)
> - * It is intended to receive data, under the current session.
> - */
> -ssize_t
> -_gnutls_recv_int(gnutls_session_t session, content_type_t type,
> - gnutls_packet_t *packet,
> - uint8_t * data, size_t data_size, void *seq,
> - unsigned int ms)
> +/* Returns a value greater than zero (>= 0) if buffers should be checked
> + * for data. */
> +static ssize_t
> +_gnutls_recv_int2(gnutls_session_t session)
> {
> int ret;
>
> - if (packet == NULL && (type != GNUTLS_ALERT && type != GNUTLS_HEARTBEAT)
> - && (data_size == 0 || data == NULL))
> - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
> -
> if (session->internals.read_eof != 0) {
> /* if we have already read an EOF
> */
> @@ -1390,37 +1380,48 @@ _gnutls_recv_int(gnutls_session_t session, content_type_t type,
> return gnutls_assert_val(ret);
>
> session->internals.recv_state = RECV_STATE_0;
> + /* Fall through: */
> case RECV_STATE_0:
>
> _dtls_async_timer_check(session);
> + return 1;
> + default:
> + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
> + }
> +}
>
> - if (packet == NULL) {
> - /* If we have enough data in the cache do not bother receiving
> - * a new packet. (in order to flush the cache)
> - */
> - ret = check_buffers(session, type, data, data_size, seq);
> - if (ret != 0)
> - return ret;
> +/* This function behaves exactly like read(). The only difference is
> + * that it accepts the gnutls_session_t and the content_type_t of data to
> + * receive (if called by the user the Content is Userdata only)
> + * It is intended to receive data, under the current session.
> + */
> +ssize_t
> +_gnutls_recv_int(gnutls_session_t session, content_type_t type,
> + uint8_t * data, size_t data_size, void *seq,
> + unsigned int ms)
> +{
> + int ret;
>
> - ret = _gnutls_recv_in_buffers(session, type, -1, ms);
> - if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
> - return gnutls_assert_val(ret);
> + if ((type != GNUTLS_ALERT && type != GNUTLS_HEARTBEAT)
> + && (data_size == 0 || data == NULL))
> + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
>
> - return check_buffers(session, type, data, data_size, seq);
> - } else {
> - ret = check_packet_buffers(session, type, packet);
> - if (ret != 0)
> - return ret;
> + ret = _gnutls_recv_int2(session);
> + if (ret <= 0)
> + return ret;
>
> - ret = _gnutls_recv_in_buffers(session, type, -1, ms);
> - if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
> - return gnutls_assert_val(ret);
> + /* If we have enough data in the cache do not bother receiving
> + * a new packet. (in order to flush the cache)
> + */
> + ret = check_buffers(session, type, data, data_size, seq);
> + if (ret != 0)
> + return ret;
>
> - return check_packet_buffers(session, type, packet);
> - }
> - default:
> - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
> - }
> + ret = _gnutls_recv_in_buffers(session, type, -1, ms);
> + if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
> + return gnutls_assert_val(ret);
> +
> + return check_buffers(session, type, data, data_size, seq);
> }
>
> /**
> @@ -1511,9 +1512,25 @@ ssize_t
> gnutls_record_recv_packet(gnutls_session_t session,
> gnutls_packet_t *packet)
> {
> - return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA, packet,
> - NULL, 0, NULL,
> - session->internals.record_timeout_ms);
> + int ret;
> +
> + if (packet == NULL)
> + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
> +
> + ret = _gnutls_recv_int2(session);
> + if (ret <= 0)
> + return ret;
> +
> + ret = check_packet_buffers(session, GNUTLS_APPLICATION_DATA, packet);
> + if (ret != 0)
> + return ret;
> +
> + ret = _gnutls_recv_in_buffers(session, GNUTLS_APPLICATION_DATA, -1,
> + session->internals.record_timeout_ms);
> + if (ret < 0 && ret != GNUTLS_E_SESSION_EOF)
> + return gnutls_assert_val(ret);
> +
> + return check_packet_buffers(session, GNUTLS_APPLICATION_DATA, packet);
> }
>
> /**
> @@ -1694,7 +1711,7 @@ int gnutls_record_uncork(gnutls_session_t session, unsigned int flags)
> ssize_t
> gnutls_record_recv(gnutls_session_t session, void *data, size_t data_size)
> {
> - return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA, NULL,
> + return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA,
> data, data_size, NULL,
> session->internals.record_timeout_ms);
> }
> @@ -1723,7 +1740,7 @@ ssize_t
> gnutls_record_recv_seq(gnutls_session_t session, void *data,
> size_t data_size, unsigned char *seq)
> {
> - return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA, NULL,
> + return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA,
> data, data_size, seq,
> session->internals.record_timeout_ms);
> }
> diff --git a/lib/record.h b/lib/record.h
> index d029586..f16df47 100644
> --- a/lib/record.h
> +++ b/lib/record.h
> @@ -45,7 +45,6 @@ _gnutls_send_int(gnutls_session_t session, content_type_t type,
> }
>
> ssize_t _gnutls_recv_int(gnutls_session_t session, content_type_t type,
> - gnutls_packet_t *packet,
> uint8_t * data,
> size_t sizeofdata, void *seq, unsigned int ms);
>
>
More information about the Gnutls-devel
mailing list