From 20b5eef40eeb9325c22f8cd1a5b1cff49501c41e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Petr=20P=C3=ADsa=C5=99?= Date: Thu, 13 Dec 2012 21:17:28 +0100 Subject: [PATCH] test: server: Use TLS call-back in HTTP --- test/simline/http.c | 9 ++++++--- test/simline/http.h | 16 +++++++++------ test/simline/server.c | 56 +++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/test/simline/http.c b/test/simline/http.c index d72b547..3a685ee 100644 --- a/test/simline/http.c +++ b/test/simline/http.c @@ -233,6 +233,8 @@ static char *uri_decode(const char *coded) { /* Call-backs set by application */ http_recv_callback_t http_recv_callback = NULL; http_send_callback_t http_send_callback = NULL; +void *http_recv_context = NULL; +void *http_send_context = NULL; /* Read a line from HTTP socket. * @socket is descriptor to read from. @@ -292,7 +294,7 @@ static int http_read_line(int socket, char **line, } /* Read data */ - got = http_recv_callback(socket, *buffer + *buffer_used, + got = http_recv_callback(http_recv_context, *buffer + *buffer_used, *buffer_size - *buffer_used, 0); if (got == -1) return HTTP_ERROR_CLIENT; @@ -320,7 +322,8 @@ static int http_write_bulk(int socket, const void *data, size_t length) { if (data == NULL && length > 0) return HTTP_ERROR_SERVER; for (end = data + length; data != end; data += written, length -= written) { - written = http_send_callback(socket, data, length, MSG_NOSIGNAL); + written = http_send_callback(http_send_context, data, length, + MSG_NOSIGNAL); if (written == -1) return HTTP_ERROR_CLIENT; } @@ -401,7 +404,7 @@ static int http_read_bulk(int socket, void **data, size_t data_length, } /* Read data */ - got = http_recv_callback(socket, *buffer + *buffer_used, + got = http_recv_callback(http_recv_context, *buffer + *buffer_used, *buffer_size - *buffer_used, 0); if (got == -1) return HTTP_ERROR_CLIENT; diff --git a/test/simline/http.h b/test/simline/http.h index b413e2a..4b31bfd 100644 --- a/test/simline/http.h +++ b/test/simline/http.h @@ -3,17 +3,21 @@ #include -/* Call-back type for non-interrupting receving from socket. See recv(2). */ -typedef ssize_t (*http_recv_callback_t) (int socket, void *buffer, +/* Call-back type for non-interrupting receiving from socket. See recv(2). + * @context is opaque pointer passed to the call-back. */ +typedef ssize_t (*http_recv_callback_t) (void *context, void *buffer, size_t length, int flags); -/* Application must set this pointer. */ +/* Application must set these pointers. */ extern http_recv_callback_t http_recv_callback; +extern void *http_recv_context; -/* Call-back type for non-interrupting sending to socket. See send(2). */ -typedef ssize_t (*http_send_callback_t) (int socket, const void *buffer, +/* Call-back type for non-interrupting sending to socket. See send(2). + * @context is opaque pointer passed to the call-back. */ +typedef ssize_t (*http_send_callback_t) (void *context, const void *buffer, size_t length, int flags); -/* Application must set this pointer. */ +/* Application must set these pointers. */ extern http_send_callback_t http_send_callback; +extern void *http_send_context; typedef enum { HTTP_ERROR_SERVER = -1, diff --git a/test/simline/server.c b/test/simline/server.c index 09facce..26bfd62 100644 --- a/test/simline/server.c +++ b/test/simline/server.c @@ -566,10 +566,11 @@ int server_out_of_order(int client_socket, /* Call-back for HTTP to receive data from socket * API is equivalent to recv(2) except automatic interrupt handling. */ -static ssize_t recv_plain(int socket, void *buffer, size_t length, int flags) { +static ssize_t recv_plain(void *context, void *buffer, size_t length, + int flags) { ssize_t retval; do { - retval = recv(socket, buffer, length, flags); + retval = recv(*(int *)context, buffer, length, flags); } while (-1 == retval && EINTR == errno); return retval; } @@ -577,16 +578,51 @@ static ssize_t recv_plain(int socket, void *buffer, size_t length, int flags) { /* Call-back for HTTP to sending data to socket * API is equivalent to send(2) except automatic interrupt handling. */ -static ssize_t send_plain(int socket, const void *buffer, size_t length, +static ssize_t send_plain(void *context, const void *buffer, size_t length, int flags) { ssize_t retval; do { - retval = send(socket, buffer, length, flags); + retval = send(*(int *)context, buffer, length, flags); } while (-1 == retval && EINTR == errno); return retval; } +/* Call-back for HTTP to receive data from TLS socket + * API is equivalent to recv(2) except automatic interrupt handling. */ +static ssize_t recv_tls(void *context, void *buffer, size_t length, + int flags) { + ssize_t retval; + do { + retval = gnutls_record_recv(context, buffer, length); + if (GNUTLS_E_REHANDSHAKE == retval) { + int error; + do { + error = gnutls_handshake(context); + } while (error < 0 && !gnutls_error_is_fatal(error)); + if (error < 0) { + fprintf(stderr, "TLS rehandshake failed: %s\n", + gnutls_strerror(error)); + return -1; + } + } + } while (GNUTLS_E_INTERRUPTED == retval || GNUTLS_E_AGAIN == retval); + return (retval < 0) ? -1 : retval; +} + + +/* Call-back for HTTP to sending data to TLS socket + * API is equivalent to send(2) except automatic interrupt handling. */ +static ssize_t send_tls(void *context, const void *buffer, size_t length, + int flags) { + ssize_t retval; + do { + retval = gnutls_record_send(context, buffer, length); + } while (GNUTLS_E_INTERRUPTED == retval || GNUTLS_E_AGAIN == retval); + return (retval < 0) ? -1 : retval; +} + + /* Start sever in separate process. * @server_process is PID of forked server * @server_address is automatically allocated TCP address of listening server @@ -612,9 +648,6 @@ int start_server(pid_t *server_process, char **server_address, int server_socket; int error; - http_recv_callback = recv_plain; - http_send_callback = send_plain; - if (server_address == NULL) { set_server_error("start_server(): Got invalid server_address pointer"); return -1; @@ -785,7 +818,11 @@ int start_server(pid_t *server_process, char **server_address, } fprintf(stderr, "Connection accepted\n"); - if (NULL != tls) { + if (NULL == tls) { + http_recv_callback = recv_plain; + http_send_callback = send_plain; + http_recv_context = http_send_context = &client_socket; + } else { /* XXX: The double type caset is to silent warning due to flaw * GnuTLS API * @@ -802,6 +839,9 @@ int start_server(pid_t *server_process, char **server_address, gnutls_deinit(tls_session); continue; } + http_recv_callback = recv_tls; + http_send_callback = send_tls; + http_recv_context = http_send_context = tls_session; } error = http_read_request(client_socket, &request); -- 2.11.4.GIT