~ne02ptzero/pistache

dd5e155d4553a2bf5642b3f048d0d4d8e6a26a05 — Dennis Jenkins 2 years ago 1c9d71a + 44e4047
Merge pull request #620 from Ne02ptzero/work/louis/sendfile_tls

Transport: Fix static file serving from SSL connections
3 files changed, 90 insertions(+), 1 deletions(-)

A include/pistache/utils.h
M src/common/transport.cc
A src/common/utils.cc
A include/pistache/utils.h => include/pistache/utils.h +39 -0
@@ 0,0 1,39 @@
/* utils.h
   Louis Solofrizzo 2019-10-17

   Utilities for pistache
*/

#pragma once

#ifdef PISTACHE_USE_SSL

#include <openssl/ssl.h>

/*!
 * \brief sendfile(2) like utility for OpenSSL contexts
 *
 * \param[out] out The SSL context
 * \param[in] in File descriptor to stream
 * \param[out] offset See below.
 * \param[in] count Number of bytes to write
 *
 * Unlike the system call, this function will bufferise data in user-space,
 * thus making it blocking and memory hungry.
 *
 * If offset is  not NULL, then it points to a variable holding the file offset
 * from which SSL_sendfile() will start reading data from in. When
 * SSL_sendfile() returns, this  variable will be set to the offset of the byte
 * following the last byte that was read.
 *
 * \note This function exists in OpenSSL3[1]. It uses KTLS features which are
 * far more superior that this function. We'll need to do the switch when
 * OpenSSL3 becomes the SSL mainline.
 *
 * \return The number of bytes written to the SSL context
 *
 * [1] https://www.openssl.org/docs/manmaster/man3/SSL_sendfile.html
 */
ssize_t SSL_sendfile(SSL *out, int in, off_t *offset, size_t count);

#endif /* PISTACHE_USE_SSL */

M src/common/transport.cc => src/common/transport.cc +16 -1
@@ 12,6 12,7 @@
#include <pistache/peer.h>
#include <pistache/tcp.h>
#include <pistache/os.h>
#include <pistache/utils.h>


namespace Pistache {


@@ 257,7 258,21 @@ Transport::asyncWriteImpl(Fd fd)
            } else {
                auto file = buffer.fd();
                off_t offset = totalWritten;
                bytesWritten = ::sendfile(fd, file, &offset, len);

#ifdef PISTACHE_USE_SSL
                auto it = peers.find(fd);

                if (it == std::end(peers))
                    throw std::runtime_error("No peer found for fd: " + std::to_string(fd));

                if (it->second->ssl() != NULL) {
                    bytesWritten = SSL_sendfile((SSL *)it->second->ssl(), file, &offset, len);
                } else {
#endif /* PISTACHE_USE_SSL */
                    bytesWritten = ::sendfile(fd, file, &offset, len);
#ifdef PISTACHE_USE_SSL
                }
#endif /* PISTACHE_USE_SSL */
            }
            if (bytesWritten < 0) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {

A src/common/utils.cc => src/common/utils.cc +35 -0
@@ 0,0 1,35 @@
/* utils.cc
   Louis Solofrizzo 2019-10-17

   Utilities for pistache
*/

#include <pistache/peer.h>
#include <unistd.h>

ssize_t SSL_sendfile(SSL *out, int in, off_t *offset, size_t count)
{
    unsigned char       buffer[4096] = { 0 };
    ssize_t             ret;
    ssize_t             written;
    size_t              to_read;

    if (in == -1)
        return -1;

    to_read = sizeof(buffer) > count ? count : sizeof(buffer);

    if (offset != NULL)
        ret = pread(in, buffer, to_read, *offset);
    else
        ret = read(in, buffer, to_read);

    if (ret == -1)
        return -1;

    written = SSL_write(out, buffer, ret);
    if (offset != NULL)
        *offset += written;

    return written;
}