libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 3b9e9c85b8dab59b73039c5bade324e07504da72
parent b8d6c063fe9e425e08652f74cb617514e6a8440d
Author: Andrey Uzunov <andrey.uzunov@gmail.com>
Date:   Fri,  5 Jul 2013 14:25:04 +0000

spdy: continue - previous one and rename tls to openssl

Diffstat:
Msrc/microspdy/Makefile.am | 2+-
Msrc/microspdy/applicationlayer.c | 6+++---
Msrc/microspdy/daemon.c | 6+++---
Msrc/microspdy/internal.h | 1-
Msrc/microspdy/io.h | 1+
Asrc/microspdy/io_openssl.c | 255+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/microspdy/io_openssl.h | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/microspdy/session.c | 24++++++++++++------------
Msrc/microspdy/structures.h | 1-
Dsrc/microspdy/tls.c | 255-------------------------------------------------------------------------------
Dsrc/microspdy/tls.h | 171-------------------------------------------------------------------------------
11 files changed, 417 insertions(+), 447 deletions(-)

diff --git a/src/microspdy/Makefile.am b/src/microspdy/Makefile.am @@ -16,7 +16,7 @@ lib_LTLIBRARIES = \ libmicrospdy_la_SOURCES = \ io.h \ - tls.h tls.c \ + io_openssl.h io_openssl.c \ structures.h structures.c \ internal.h internal.c \ daemon.h daemon.c \ diff --git a/src/microspdy/applicationlayer.c b/src/microspdy/applicationlayer.c @@ -239,7 +239,7 @@ SPDY_init () "Buffer size is less than max supported frame size!"); SPDYF_ASSERT(SPDY_MAX_SUPPORTED_FRAME_SIZE >= 32, "Max supported frame size must be bigger than the minimal value!"); - SPDYF_tls_global_init(); + SPDYF_openssl_global_init(); return SPDY_YES; } @@ -248,8 +248,8 @@ void SPDY_deinit () { //currently nothing to be freed/deinited - //SPDYF_tls_global_deinit doesn't do anything now - //SPDYF_tls_global_deinit(); + //SPDYF_openssl_global_deinit doesn't do anything now + //SPDYF_openssl_global_deinit(); } diff --git a/src/microspdy/daemon.c b/src/microspdy/daemon.c @@ -26,7 +26,7 @@ #include "structures.h" #include "internal.h" #include "session.h" -#include "tls.h" +#include "io.h" /** @@ -191,8 +191,8 @@ SPDYF_start_daemon_va (uint16_t port, memset (daemon, 0, sizeof (struct SPDY_Daemon)); daemon->socket_fd = -1; daemon->port = port; - daemon->fio_init = &SPDYF_tls_init; - daemon->fio_deinit = &SPDYF_tls_deinit; + daemon->fio_init = &SPDYF_openssl_init; + daemon->fio_deinit = &SPDYF_openssl_deinit; if (NULL == (daemon->certfile = strdup (certfile))) { SPDYF_DEBUG("str"); diff --git a/src/microspdy/internal.h b/src/microspdy/internal.h @@ -27,7 +27,6 @@ #include "platform.h" #include "microspdy.h" -#include "tls.h" /* size of read buffers for each connection * must be at least the size of SPDY_MAX_SUPPORTED_FRAME_SIZE */ diff --git a/src/microspdy/io.h b/src/microspdy/io.h @@ -26,6 +26,7 @@ #define IO_H #include "platform.h" +#include "io_openssl.h" /** diff --git a/src/microspdy/io_openssl.c b/src/microspdy/io_openssl.c @@ -0,0 +1,255 @@ +/* + This file is part of libmicrospdy + Copyright (C) 2012 Andrey Uzunov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file io_openssl.c + * @brief TLS handling using libssl. The current code assumes that + * blocking I/O is in use. + * @author Andrey Uzunov + */ + +#include "platform.h" +#include "internal.h" +#include "session.h" +#include "io_openssl.h" + + +/** + * Callback to advertise spdy ver. 3 in Next Protocol Negotiation + * + * @param ssl openssl context for a connection + * @param out must be set to the raw data that is advertised in NPN + * @param outlen must be set to size of out + * @param arg + * @return SSL_TLSEXT_ERR_OK to do advertising + */ +static int +spdyf_next_protos_advertised_cb (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) +{ + (void)ssl; + (void)arg; + static unsigned char npn_spdy3[] = {0x06, // length of "spdy/3" + 0x73,0x70,0x64,0x79,0x2f,0x33};// spdy/3 + + *out = npn_spdy3; + *outlen = 7; // total length of npn_spdy3 + return SSL_TLSEXT_ERR_OK; +} + + +void +SPDYF_openssl_global_init() +{ + //error strings are now not used by the lib + //SSL_load_error_strings(); + //init libssl + SSL_library_init(); //always returns 1 + //the table for looking up algos is not used now by the lib + //OpenSSL_add_all_algorithms(); +} + + +void +SPDYF_openssl_global_deinit() +{ + //if SSL_load_error_strings was called + //ERR_free_strings(); + //if OpenSSL_add_all_algorithms was called + //EVP_cleanup(); +} + + +int +SPDYF_openssl_init(struct SPDY_Daemon *daemon) +{ + //create ssl context. TLSv1 used + if(NULL == (daemon->io_context = SSL_CTX_new(TLSv1_server_method()))) + { + SPDYF_DEBUG("Couldn't create ssl context"); + return SPDY_NO; + } + //set options for tls + //TODO DH is not enabled for easier debugging + //SSL_CTX_set_options(daemon->io_context, SSL_OP_SINGLE_DH_USE); + + //TODO here session tickets are disabled for easier debuging with + //wireshark when using Chrome + //SSL_OP_NO_COMPRESSION disables TLS compression to avoid CRIME attack + SSL_CTX_set_options(daemon->io_context, SSL_OP_NO_TICKET | SSL_OP_NO_COMPRESSION); + if(1 != SSL_CTX_use_certificate_file(daemon->io_context, daemon->certfile , SSL_FILETYPE_PEM)) + { + SPDYF_DEBUG("Couldn't load the cert file"); + SSL_CTX_free(daemon->io_context); + return SPDY_NO; + } + if(1 != SSL_CTX_use_PrivateKey_file(daemon->io_context, daemon->keyfile, SSL_FILETYPE_PEM)) + { + SPDYF_DEBUG("Couldn't load the name file"); + SSL_CTX_free(daemon->io_context); + return SPDY_NO; + } + SSL_CTX_set_next_protos_advertised_cb(daemon->io_context, &spdyf_next_protos_advertised_cb, NULL); + //TODO only RC4-SHA is used to make it easy to debug with wireshark + if (1 != SSL_CTX_set_cipher_list(daemon->io_context, "RC4-SHA")) + { + SPDYF_DEBUG("Couldn't set the desired cipher list"); + SSL_CTX_free(daemon->io_context); + return SPDY_NO; + } + + return SPDY_YES; +} + + +void +SPDYF_openssl_deinit(struct SPDY_Daemon *daemon) +{ + SSL_CTX_free(daemon->io_context); +} + + +int +SPDYF_openssl_new_session(struct SPDY_Session *session) +{ + int ret; + + if(NULL == (session->io_context = SSL_new(session->daemon->io_context))) + { + SPDYF_DEBUG("Couldn't create ssl structure"); + return SPDY_NO; + } + if(1 != (ret = SSL_set_fd(session->io_context, session->socket_fd))) + { + SPDYF_DEBUG("SSL_set_fd %i",ret); + SSL_free(session->io_context); + session->io_context = NULL; + return SPDY_NO; + } + + //for non-blocking I/O SSL_accept may return -1 + //and this function won't work + if(1 != (ret = SSL_accept(session->io_context))) + { + SPDYF_DEBUG("SSL_accept %i",ret); + SSL_free(session->io_context); + session->io_context = NULL; + return SPDY_NO; + } + /* alternatively + SSL_set_accept_state(session->io_context); + * may be called and then the negotiation will be done on reading + */ + + return SPDY_YES; +} + + +void +SPDYF_openssl_close_session(struct SPDY_Session *session) +{ + //SSL_shutdown sends TLS "close notify" as in TLS standard. + //The function may fail as it waits for the other party to also close + //the TLS session. The lib just sends it and will close the socket + //after that because the browsers don't seem to care much about + //"close notify" + SSL_shutdown(session->io_context); + + SSL_free(session->io_context); +} + + +int +SPDYF_openssl_recv(struct SPDY_Session *session, + void * buffer, + size_t size) +{ + int ret; + int n = SSL_read(session->io_context, + buffer, + size); + //if(n > 0) SPDYF_DEBUG("recvd: %i",n); + if (n <= 0) + { + ret = SSL_get_error(session->io_context, n); + switch(ret) + { + case SSL_ERROR_ZERO_RETURN: + return 0; + + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + return SPDY_IO_ERROR_AGAIN; + + case SSL_ERROR_SYSCALL: + if(EINTR == errno) + return SPDY_IO_ERROR_AGAIN; + + default: + return SPDY_IO_ERROR_ERROR; + } + } + + return n; +} + + +int +SPDYF_openssl_send(struct SPDY_Session *session, + const void * buffer, + size_t size) +{ + int ret; + + int n = SSL_write(session->io_context, + buffer, + size); + //if(n > 0) SPDYF_DEBUG("sent: %i",n); + if (n <= 0) + { + ret = SSL_get_error(session->io_context, n); + switch(ret) + { + case SSL_ERROR_ZERO_RETURN: + return 0; + + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + return SPDY_IO_ERROR_AGAIN; + + case SSL_ERROR_SYSCALL: + if(EINTR == errno) + return SPDY_IO_ERROR_AGAIN; + + default: + return SPDY_IO_ERROR_ERROR; + } + } + + return n; +} + + +int +SPDYF_openssl_is_pending(struct SPDY_Session *session) +{ + /* From openssl docs: + * BUGS +SSL_pending() takes into account only bytes from the TLS/SSL record that is currently being processed (if any). If the SSL object's read_ahead flag is set, additional protocol bytes may have been read containing more TLS/SSL records; these are ignored by SSL_pending(). + */ + return SSL_pending(session->io_context) > 0 ? SPDY_YES : SPDY_NO; +} diff --git a/src/microspdy/io_openssl.h b/src/microspdy/io_openssl.h @@ -0,0 +1,142 @@ +/* + This file is part of libmicrospdy + Copyright (C) 2012 Andrey Uzunov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file io_openssl.h + * @brief TLS handling. openssl with NPN is used, but as long as the + * functions conform to this interface file, other libraries + * can be used. + * @author Andrey Uzunov + */ + +#ifndef IO_OPENSSL_H +#define IO_OPENSSL_H + +#include "platform.h" +#include "io.h" +#include <openssl/err.h> +#include <openssl/ssl.h> +#include <openssl/rand.h> + + +/** + * Global initializing of openssl. Must be called only once in the program. + * + */ +void +SPDYF_openssl_global_init(); + + +/** + * Global deinitializing of openssl for the whole program. Should be called + * at the end of the program. + * + */ +void +SPDYF_openssl_global_deinit(); + + +/** + * Initializing of openssl for a specific daemon. + * Must be called when the daemon starts. + * + * @param daemon SPDY_Daemon for which openssl will be used. Daemon's + * certificate and key file are used. + * @return SPDY_YES on success or SPDY_NO on error + */ +int +SPDYF_openssl_init(struct SPDY_Daemon *daemon); + + +/** + * Deinitializing openssl for a daemon. Should be called + * when the deamon is stopped. + * + * @param daemon SPDY_Daemon which is being stopped + */ +void +SPDYF_openssl_deinit(struct SPDY_Daemon *daemon); + + +/** + * Initializing openssl for a specific connection. Must be called + * after the connection has been accepted. + * + * @param session SPDY_Session whose socket will be used by openssl + * @return SPDY_NO if some openssl funcs fail. SPDY_YES otherwise + */ +int +SPDYF_openssl_new_session(struct SPDY_Session *session); + + +/** + * Deinitializing openssl for a specific connection. Should be called + * closing session's socket. + * + * @param session SPDY_Session whose socket is used by openssl + */ +void +SPDYF_openssl_close_session(struct SPDY_Session *session); + + +/** + * Reading from a TLS socket. Reads available data and put it to the + * buffer. + * + * @param session for which data is received + * @param buffer where data from the socket will be written to + * @param size of the buffer + * @return number of bytes (at most size) read from the TLS connection + * 0 if the other party has closed the connection + * SPDY_IO_ERROR code on error + */ +int +SPDYF_openssl_recv(struct SPDY_Session *session, + void * buffer, + size_t size); + + +/** + * Writing to a TLS socket. Writes the data given into the buffer to the + * TLS socket. + * + * @param session whose context is used + * @param buffer from where data will be written to the socket + * @param size number of bytes to be taken from the buffer + * @return number of bytes (at most size) from the buffer that has been + * written to the TLS connection + * 0 if the other party has closed the connection + * SPDY_IO_ERROR code on error + */ +int +SPDYF_openssl_send(struct SPDY_Session *session, + const void * buffer, + size_t size); + + +/** + * Checks if there is data staying in the buffers of the underlying + * system that waits to be read. + * + * @param session which is checked + * @return SPDY_YES if data is pending or SPDY_NO otherwise + */ +int +SPDYF_openssl_is_pending(struct SPDY_Session *session); + +#endif diff --git a/src/microspdy/session.c b/src/microspdy/session.c @@ -28,8 +28,8 @@ #include "internal.h" #include "session.h" #include "compression.h" -#include "tls.h" #include "stream.h" +#include "io.h" /** @@ -826,7 +826,7 @@ SPDYF_session_read (struct SPDY_Session *session) switch(bytes_read) { - case SPDY_TLS_ERROR_CLOSED: + case SPDY_IO_ERROR_CLOSED: //The TLS connection was closed by the other party, clean //or not shutdown (session->socket_fd, SHUT_RD); @@ -834,7 +834,7 @@ SPDYF_session_read (struct SPDY_Session *session) session->status = SPDY_SESSION_STATUS_CLOSING; return SPDY_YES; - case SPDY_TLS_ERROR_ERROR: + case SPDY_IO_ERROR_ERROR: //any kind of error in the TLS subsystem //try to prepare GOAWAY frame SPDYF_prepare_goaway(session, SPDY_GOAWAY_STATUS_INTERNAL_ERROR, false); @@ -842,7 +842,7 @@ SPDYF_session_read (struct SPDY_Session *session) session->status = SPDY_SESSION_STATUS_FLUSHING; return SPDY_YES; - case SPDY_TLS_ERROR_AGAIN: + case SPDY_IO_ERROR_AGAIN: //read or write should be called again; leave it for the //next time return SPDY_NO; @@ -958,7 +958,7 @@ SPDYF_session_write (struct SPDY_Session *session, bool only_one_frame) switch(bytes_written) { - case SPDY_TLS_ERROR_CLOSED: + case SPDY_IO_ERROR_CLOSED: //The TLS connection was closed by the other party, clean //or not shutdown (session->socket_fd, SHUT_RD); @@ -966,13 +966,13 @@ SPDYF_session_write (struct SPDY_Session *session, bool only_one_frame) session->status = SPDY_SESSION_STATUS_CLOSING; return SPDY_YES; - case SPDY_TLS_ERROR_ERROR: + case SPDY_IO_ERROR_ERROR: //any kind of error in the TLS subsystem //forbid more writing session->status = SPDY_SESSION_STATUS_CLOSING; return SPDY_YES; - case SPDY_TLS_ERROR_AGAIN: + case SPDY_IO_ERROR_AGAIN: //read or write should be called again; leave it for the //next time; return from the function as we do not now //whether reading or writing is needed @@ -1306,11 +1306,11 @@ SPDYF_session_accept(struct SPDY_Daemon *daemon) session->daemon = daemon; session->socket_fd = new_socket_fd; - session->fio_new_session = &SPDYF_tls_new_session; - session->fio_close_session = &SPDYF_tls_close_session; - session->fio_is_pending = &SPDYF_tls_is_pending; - session->fio_recv = &SPDYF_tls_recv; - session->fio_send = &SPDYF_tls_send; + session->fio_new_session = &SPDYF_openssl_new_session; + session->fio_close_session = &SPDYF_openssl_close_session; + session->fio_is_pending = &SPDYF_openssl_is_pending; + session->fio_recv = &SPDYF_openssl_recv; + session->fio_send = &SPDYF_openssl_send; //init TLS context, handshake will be done if(SPDY_YES != session->fio_new_session(session)) diff --git a/src/microspdy/structures.h b/src/microspdy/structures.h @@ -28,7 +28,6 @@ #include "platform.h" #include "microspdy.h" -#include "tls.h" #include "io.h" diff --git a/src/microspdy/tls.c b/src/microspdy/tls.c @@ -1,255 +0,0 @@ -/* - This file is part of libmicrospdy - Copyright (C) 2012 Andrey Uzunov - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/** - * @file tls.c - * @brief TLS handling using libssl. The current code assumes that - * blocking I/O is in use. - * @author Andrey Uzunov - */ - -#include "platform.h" -#include "internal.h" -#include "session.h" -#include "tls.h" - - -/** - * Callback to advertise spdy ver. 3 in Next Protocol Negotiation - * - * @param ssl openssl context for a connection - * @param out must be set to the raw data that is advertised in NPN - * @param outlen must be set to size of out - * @param arg - * @return SSL_TLSEXT_ERR_OK to do advertising - */ -static int -spdyf_next_protos_advertised_cb (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) -{ - (void)ssl; - (void)arg; - static unsigned char npn_spdy3[] = {0x06, // length of "spdy/3" - 0x73,0x70,0x64,0x79,0x2f,0x33};// spdy/3 - - *out = npn_spdy3; - *outlen = 7; // total length of npn_spdy3 - return SSL_TLSEXT_ERR_OK; -} - - -void -SPDYF_tls_global_init() -{ - //error strings are now not used by the lib - //SSL_load_error_strings(); - //init libssl - SSL_library_init(); //always returns 1 - //the table for looking up algos is not used now by the lib - //OpenSSL_add_all_algorithms(); -} - - -void -SPDYF_tls_global_deinit() -{ - //if SSL_load_error_strings was called - //ERR_free_strings(); - //if OpenSSL_add_all_algorithms was called - //EVP_cleanup(); -} - - -int -SPDYF_tls_init(struct SPDY_Daemon *daemon) -{ - //create ssl context. TLSv1 used - if(NULL == (daemon->io_context = SSL_CTX_new(TLSv1_server_method()))) - { - SPDYF_DEBUG("Couldn't create ssl context"); - return SPDY_NO; - } - //set options for tls - //TODO DH is not enabled for easier debugging - //SSL_CTX_set_options(daemon->io_context, SSL_OP_SINGLE_DH_USE); - - //TODO here session tickets are disabled for easier debuging with - //wireshark when using Chrome - //SSL_OP_NO_COMPRESSION disables TLS compression to avoid CRIME attack - SSL_CTX_set_options(daemon->io_context, SSL_OP_NO_TICKET | SSL_OP_NO_COMPRESSION); - if(1 != SSL_CTX_use_certificate_file(daemon->io_context, daemon->certfile , SSL_FILETYPE_PEM)) - { - SPDYF_DEBUG("Couldn't load the cert file"); - SSL_CTX_free(daemon->io_context); - return SPDY_NO; - } - if(1 != SSL_CTX_use_PrivateKey_file(daemon->io_context, daemon->keyfile, SSL_FILETYPE_PEM)) - { - SPDYF_DEBUG("Couldn't load the name file"); - SSL_CTX_free(daemon->io_context); - return SPDY_NO; - } - SSL_CTX_set_next_protos_advertised_cb(daemon->io_context, &spdyf_next_protos_advertised_cb, NULL); - //TODO only RC4-SHA is used to make it easy to debug with wireshark - if (1 != SSL_CTX_set_cipher_list(daemon->io_context, "RC4-SHA")) - { - SPDYF_DEBUG("Couldn't set the desired cipher list"); - SSL_CTX_free(daemon->io_context); - return SPDY_NO; - } - - return SPDY_YES; -} - - -void -SPDYF_tls_deinit(struct SPDY_Daemon *daemon) -{ - SSL_CTX_free(daemon->io_context); -} - - -int -SPDYF_tls_new_session(struct SPDY_Session *session) -{ - int ret; - - if(NULL == (session->io_context = SSL_new(session->daemon->io_context))) - { - SPDYF_DEBUG("Couldn't create ssl structure"); - return SPDY_NO; - } - if(1 != (ret = SSL_set_fd(session->io_context, session->socket_fd))) - { - SPDYF_DEBUG("SSL_set_fd %i",ret); - SSL_free(session->io_context); - session->io_context = NULL; - return SPDY_NO; - } - - //for non-blocking I/O SSL_accept may return -1 - //and this function won't work - if(1 != (ret = SSL_accept(session->io_context))) - { - SPDYF_DEBUG("SSL_accept %i",ret); - SSL_free(session->io_context); - session->io_context = NULL; - return SPDY_NO; - } - /* alternatively - SSL_set_accept_state(session->io_context); - * may be called and then the negotiation will be done on reading - */ - - return SPDY_YES; -} - - -void -SPDYF_tls_close_session(struct SPDY_Session *session) -{ - //SSL_shutdown sends TLS "close notify" as in TLS standard. - //The function may fail as it waits for the other party to also close - //the TLS session. The lib just sends it and will close the socket - //after that because the browsers don't seem to care much about - //"close notify" - SSL_shutdown(session->io_context); - - SSL_free(session->io_context); -} - - -int -SPDYF_tls_recv(struct SPDY_Session *session, - void * buffer, - size_t size) -{ - int ret; - int n = SSL_read(session->io_context, - buffer, - size); - //if(n > 0) SPDYF_DEBUG("recvd: %i",n); - if (n <= 0) - { - ret = SSL_get_error(session->io_context, n); - switch(ret) - { - case SSL_ERROR_ZERO_RETURN: - return 0; - - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - return SPDY_TLS_ERROR_AGAIN; - - case SSL_ERROR_SYSCALL: - if(EINTR == errno) - return SPDY_TLS_ERROR_AGAIN; - - default: - return SPDY_TLS_ERROR_ERROR; - } - } - - return n; -} - - -int -SPDYF_tls_send(struct SPDY_Session *session, - const void * buffer, - size_t size) -{ - int ret; - - int n = SSL_write(session->io_context, - buffer, - size); - //if(n > 0) SPDYF_DEBUG("sent: %i",n); - if (n <= 0) - { - ret = SSL_get_error(session->io_context, n); - switch(ret) - { - case SSL_ERROR_ZERO_RETURN: - return 0; - - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - return SPDY_TLS_ERROR_AGAIN; - - case SSL_ERROR_SYSCALL: - if(EINTR == errno) - return SPDY_TLS_ERROR_AGAIN; - - default: - return SPDY_TLS_ERROR_ERROR; - } - } - - return n; -} - - -int -SPDYF_tls_is_pending(struct SPDY_Session *session) -{ - /* From openssl docs: - * BUGS -SSL_pending() takes into account only bytes from the TLS/SSL record that is currently being processed (if any). If the SSL object's read_ahead flag is set, additional protocol bytes may have been read containing more TLS/SSL records; these are ignored by SSL_pending(). - */ - return SSL_pending(session->io_context) > 0 ? SPDY_YES : SPDY_NO; -} diff --git a/src/microspdy/tls.h b/src/microspdy/tls.h @@ -1,171 +0,0 @@ -/* - This file is part of libmicrospdy - Copyright (C) 2012 Andrey Uzunov - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/** - * @file tls.h - * @brief TLS handling. openssl with NPN is used, but as long as the - * functions conform to this interface file, other libraries - * can be used. - * @author Andrey Uzunov - */ - -#ifndef TLS_H -#define TLS_H - -#include "platform.h" -#include <openssl/err.h> -#include <openssl/ssl.h> -#include <openssl/rand.h> - -/* macros used in other files instead of types. - * useful in case of changing openssl to something else */ -//#define SPDYF_TLS_SESSION_CONTEXT SSL -//#define SPDYF_TLS_DAEMON_CONTEXT SSL_CTX - - -/** - * Used for return code when reading and writing to the TLS socket. - */ -enum SPDY_TLS_ERROR -{ - /** - * The connection was closed by the other party. - */ - SPDY_TLS_ERROR_CLOSED = 0, - - /** - * Any kind of error ocurred. The session has to be closed. - */ - SPDY_TLS_ERROR_ERROR = -2, - - /** - * The function had to return without processing any data. The whole - * cycle of events has to be called again (SPDY_run) as something - * either has to be written or read or the the syscall was - * interrupted by a signal. - */ - SPDY_TLS_ERROR_AGAIN = -3, -}; - - -/** - * Global initializing of openssl. Must be called only once in the program. - * - */ -void -SPDYF_tls_global_init(); - - -/** - * Global deinitializing of openssl for the whole program. Should be called - * at the end of the program. - * - */ -void -SPDYF_tls_global_deinit(); - - -/** - * Initializing of openssl for a specific daemon. - * Must be called when the daemon starts. - * - * @param daemon SPDY_Daemon for which openssl will be used. Daemon's - * certificate and key file are used. - * @return SPDY_YES on success or SPDY_NO on error - */ -int -SPDYF_tls_init(struct SPDY_Daemon *daemon); - - -/** - * Deinitializing openssl for a daemon. Should be called - * when the deamon is stopped. - * - * @param daemon SPDY_Daemon which is being stopped - */ -void -SPDYF_tls_deinit(struct SPDY_Daemon *daemon); - - -/** - * Initializing openssl for a specific connection. Must be called - * after the connection has been accepted. - * - * @param session SPDY_Session whose socket will be used by openssl - * @return SPDY_NO if some openssl funcs fail. SPDY_YES otherwise - */ -int -SPDYF_tls_new_session(struct SPDY_Session *session); - - -/** - * Deinitializing openssl for a specific connection. Should be called - * closing session's socket. - * - * @param session SPDY_Session whose socket is used by openssl - */ -void -SPDYF_tls_close_session(struct SPDY_Session *session); - - -/** - * Reading from a TLS socket. Reads available data and put it to the - * buffer. - * - * @param session for which data is received - * @param buffer where data from the socket will be written to - * @param size of the buffer - * @return number of bytes (at most size) read from the TLS connection - * 0 if the other party has closed the connection - * SPDY_TLS_ERROR code on error - */ -int -SPDYF_tls_recv(struct SPDY_Session *session, - void * buffer, - size_t size); - - -/** - * Writing to a TLS socket. Writes the data given into the buffer to the - * TLS socket. - * - * @param session whose context is used - * @param buffer from where data will be written to the socket - * @param size number of bytes to be taken from the buffer - * @return number of bytes (at most size) from the buffer that has been - * written to the TLS connection - * 0 if the other party has closed the connection - * SPDY_TLS_ERROR code on error - */ -int -SPDYF_tls_send(struct SPDY_Session *session, - const void * buffer, - size_t size); - - -/** - * Checks if there is data staying in the buffers of the underlying - * system that waits to be read. - * - * @param session which is checked - * @return SPDY_YES if data is pending or SPDY_NO otherwise - */ -int -SPDYF_tls_is_pending(struct SPDY_Session *session); - -#endif