diff options
author | Frantisek Krenzelok <krenzelok.frantisek@gmail.com> | 2021-11-16 12:05:53 +0100 |
---|---|---|
committer | Frantisek Krenzelok <krenzelok.frantisek@gmail.com> | 2022-02-22 20:18:44 +0100 |
commit | 617f71e2e354eb391b27878c22109191f8262921 (patch) | |
tree | 78d80db302df46875d930e6677ebc66925060561 | |
parent | ad20dfc64d9c55129c36fa13f3ee2f93951d7bbf (diff) | |
download | gnutls-617f71e2e354eb391b27878c22109191f8262921.tar.gz |
ktls: sendfile
added API function: gnutls_record_send_file().
added: _gnutls_ktls_send_file() function which increases the performance
by offloading the file encryption to kernel, thus the data never goes
to userspace.
updated tests/gnutls_ktls to cover new API
Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 2 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/record.c | 24 | ||||
-rw-r--r-- | lib/system/ktls.c | 31 | ||||
-rw-r--r-- | lib/system/ktls.h | 2 | ||||
-rw-r--r-- | tests/gnutls_ktls.c | 58 |
6 files changed, 115 insertions, 3 deletions
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 482e9653c8..7dac7b7054 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1519,6 +1519,8 @@ ssize_t gnutls_record_send2(gnutls_session_t session, const void *data, ssize_t gnutls_record_send_range(gnutls_session_t session, const void *data, size_t data_size, const gnutls_range_st * range); +ssize_t gnutls_record_send_file(gnutls_session_t session, int fd, + off_t *offset, size_t count); ssize_t gnutls_record_recv(gnutls_session_t session, void *data, size_t data_size); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 5a2e8ce947..27be1284f4 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1384,6 +1384,7 @@ GNUTLS_3_7_4 { global: gnutls_ciphersuite_get; + gnutls_record_send_file; local: *; } GNUTLS_3_7_3; diff --git a/lib/record.c b/lib/record.c index ee271b5118..920a60f29a 100644 --- a/lib/record.c +++ b/lib/record.c @@ -55,6 +55,7 @@ #include <xsize.h> #include "locks.h" #include "system/ktls.h" +#include <sys/sendfile.h> struct tls_record_st { uint16_t header_size; @@ -2134,6 +2135,29 @@ ssize_t gnutls_record_send_early_data(gnutls_session_t session, } /** + * gnutls_record_send_file: + * @session: is a #gnutls_session_t type. + * @fd: file descriptor from which to read data. + * @offset: position in file from which to start reading. + * after function returns, it point to position following + * last read byte. + * @count: is the length of the data to be read from file and send. + * + * sends data via sendfile function. + * + * Returns: The number of bytes sent, or a negative error code. + **/ +ssize_t gnutls_record_send_file(gnutls_session_t session, int fd, + off_t *offset, size_t count) +{ + if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND)) { + return _gnutls_ktls_send_file(session, fd, offset, count); + } else { + return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); + } +} + +/** * gnutls_record_recv_early_data: * @session: is a #gnutls_session_t type. * @data: the buffer that the data will be read into diff --git a/lib/system/ktls.c b/lib/system/ktls.c index f156f08ab2..92c5b36073 100644 --- a/lib/system/ktls.c +++ b/lib/system/ktls.c @@ -32,6 +32,7 @@ #include <unistd.h> #include <errno.h> #include "ext/session_ticket.h" +#include <sys/sendfile.h> /** * gnutls_transport_is_ktls_enabled: @@ -261,6 +262,31 @@ int _gnutls_ktls_set_keys(gnutls_session_t session) return 0; } +ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd, + off_t *offset, size_t count) +{ + ssize_t ret; + int sockin, sockout; + + assert(session != NULL); + + gnutls_transport_get_int2(session, &sockin, &sockout); + + ret = sendfile(sockout, fd, offset, count); + if (ret == -1){ + switch(errno) { + case EINTR: + return GNUTLS_E_INTERRUPTED; + case EAGAIN: + return GNUTLS_E_AGAIN; + default: + return GNUTLS_E_PUSH_ERROR; + } + } + + return ret; +} + int _gnutls_ktls_send_control_msg(gnutls_session_t session, unsigned char record_type, const void *data, size_t data_size) { @@ -433,6 +459,11 @@ int _gnutls_ktls_set_keys(gnutls_session_t session) { return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } +ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd, + off_t *offset, size_t count) { + return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); +} + int _gnutls_ktls_send_control_msg(gnutls_session_t session, unsigned char record_type, const void *data, size_t data_size) { return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); diff --git a/lib/system/ktls.h b/lib/system/ktls.h index fb5c4eef6b..8a98a8eb8f 100644 --- a/lib/system/ktls.h +++ b/lib/system/ktls.h @@ -5,6 +5,8 @@ void _gnutls_ktls_enable(gnutls_session_t session); int _gnutls_ktls_set_keys(gnutls_session_t session); +ssize_t _gnutls_ktls_send_file(gnutls_session_t session, int fd, + off_t *offset, size_t count); int _gnutls_ktls_send_control_msg(gnutls_session_t session, unsigned char record_type, const void *data, size_t data_size); #define _gnutls_ktls_send(x, y, z) _gnutls_ktls_send_control_msg(x, GNUTLS_APPLICATION_DATA, y, z); diff --git a/tests/gnutls_ktls.c b/tests/gnutls_ktls.c index 07fd4d8adb..3966e2b10a 100644 --- a/tests/gnutls_ktls.c +++ b/tests/gnutls_ktls.c @@ -45,7 +45,6 @@ static void client_log_func(int level, const char *str) #define MAX_BUF 1024 #define MSG "Hello world!" - static void client(int fd, const char *prio) { int ret; @@ -90,6 +89,7 @@ static void client(int fd, const char *prio) } /* server send message via gnutls_record_send */ + memset(buffer, 0, sizeof(buffer)); do{ ret = gnutls_record_recv(session, buffer, sizeof(buffer)); } @@ -112,6 +112,29 @@ static void client(int fd, const char *prio) if (debug) success ("client: messages received\n"); + /* server send message via gnutls_record_sendfile */ + memset(buffer, 0, sizeof(buffer)); + do{ + ret = gnutls_record_recv(session, buffer, sizeof(buffer)); + } + while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); + + if (ret == 0) { + success + ("client: Peer has closed the TLS connection\n"); + goto end; + } else if (ret < 0) { + fail("client: Error: %s\n", gnutls_strerror(ret)); + goto end; + } + + if(strncmp(buffer, MSG, ret)){ + fail("client: Message doesn't match\n"); + goto end; + } + + if (debug) + success ("client: messages received\n"); ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); if (ret < 0) { @@ -198,8 +221,38 @@ static void server(int fd, const char *prio) goto end; } - ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); + /* send file + */ + FILE *fp = tmpfile(); + if (fp == NULL){ + fail("temporary file for testing couldn't be created"); + ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); + if (ret < 0) + fail("server: error in closing session: %s\n", gnutls_strerror(ret)); + goto end; + } + + fputs(MSG, fp); + rewind(fp); + + off_t offset = 0; + if (fp == NULL) { + fail("server: couldn't open file for testing ...send_file() function"); + goto end; + } + + do { + ret = gnutls_record_send_file(session, fileno(fp), &offset, 512); + } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); + if (ret < 0) { + fail("server: data sending has failed (%s)\n\n", + gnutls_strerror(ret)); + goto end; + } + + ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); + if (ret < 0) fail("server: error in closing session: %s\n", gnutls_strerror(ret)); ret = 0; @@ -217,7 +270,6 @@ end: if (debug) success("server: finished\n"); - } } static void ch_handler(int sig) |