summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrantisek Krenzelok <krenzelok.frantisek@gmail.com>2021-11-16 12:05:53 +0100
committerFrantisek Krenzelok <krenzelok.frantisek@gmail.com>2022-02-22 20:18:44 +0100
commit617f71e2e354eb391b27878c22109191f8262921 (patch)
tree78d80db302df46875d930e6677ebc66925060561
parentad20dfc64d9c55129c36fa13f3ee2f93951d7bbf (diff)
downloadgnutls-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.in2
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/record.c24
-rw-r--r--lib/system/ktls.c31
-rw-r--r--lib/system/ktls.h2
-rw-r--r--tests/gnutls_ktls.c58
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)