net/socket.hpp | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 141 insertions(+), 13 deletions(-)
New commits: commit a3b6ef4a76aeb5daf4cbca3f25ca0983020bdca6 Author: Ashod Nakashian <[email protected]> Date: Fri Feb 17 19:05:53 2017 -0500 nb: basic SSL socket implementation Change-Id: Iaa2da47df17f14dfded44a8cf805020e8ef6b1ff Reviewed-on: https://gerrit.libreoffice.org/34395 Reviewed-by: Ashod Nakashian <[email protected]> Tested-by: Ashod Nakashian <[email protected]> diff --git a/net/socket.hpp b/net/socket.hpp index 69d2710..95d4991 100644 --- a/net/socket.hpp +++ b/net/socket.hpp @@ -339,11 +339,6 @@ protected: class StreamSocket : public BufferingSocket { public: - StreamSocket() : - BufferingSocket() - { - } - bool readIncomingData() override { ssize_t len; @@ -391,26 +386,74 @@ protected: class SslStreamSocket : public BufferingSocket { public: - SslStreamSocket() : - BufferingSocket() + bool readIncomingData() override { + ssize_t len; + char buf[4096]; + do + { + len = SSL_read(_ssl, buf, sizeof(buf)); + } + while (len < 0 && errno == EINTR); + + len = handleSslState(len); + + if (len > 0) + { + // We have more data, let the application consume it, if possible. + assert (len < ssize_t(sizeof(buf))); + _inBuffer.insert(_inBuffer.end(), &buf[0], &buf[len]); + handleIncomingMessage(); + } + // else poll will handle errors. + + return len != 0; // zero is eof / clean socket close. } - bool readIncomingData() override + void writeOutgoingData() override { - //TODO: - return true; + // Should never call SSL_write with 0 length data. + assert (_outBuffer.size() > 0); + ssize_t len; + do + { + len = SSL_write(_ssl, &_outBuffer[0], _outBuffer.size()); + } + while (len < 0 && errno == EINTR); + + len = handleSslState(len); + + if (len > 0) + { + // We've sent some data, remove from the buffer. + _outBuffer.erase(_outBuffer.begin(), + _outBuffer.begin() + len); + } + // else poll will handle errors } - void writeOutgoingData() override + int getPollEvents() override { - //TODO; + if (_sslWantsTo == SslWantsTo::Read) + { + // Must read next before attempting to write. + return POLLIN; + } + else if (_sslWantsTo == SslWantsTo::Write) + { + // Must write next before attempting to read. + return POLLOUT; + } + + // Do whatever makes sense based on buffer state. + return (_outBuffer.empty() ? POLLIN : (POLLIN | POLLOUT)); } protected: SslStreamSocket(const int fd) : BufferingSocket(fd), - _ssl(nullptr) + _ssl(nullptr), + _sslWantsTo(SslWantsTo::ReadOrWrite) { BIO* bio = BIO_new(BIO_s_socket()); if (bio == nullptr) @@ -437,7 +480,92 @@ protected: template<class T> friend class ServerSocket; private: + + /// The possible next I/O operation that SSL want to do. + enum class SslWantsTo + { + ReadOrWrite, + Read, + Write + }; + + /// Handles the state of SSL after read or write. + int handleSslState(const int rc) + { + if (rc > 0) + { + // Success: Reset so we can do either. + _sslWantsTo = SslWantsTo::ReadOrWrite; + return rc; + } + + // Last operation failed. Find out if SSL was trying + // to do something different that failed, or not. + const int sslError = SSL_get_error(_ssl, rc); + switch (sslError) + { + case SSL_ERROR_ZERO_RETURN: + // Shutdown complete, we're disconnected. + return 0; + + case SSL_ERROR_WANT_READ: + _sslWantsTo = SslWantsTo::Read; + return rc; + + case SSL_ERROR_WANT_WRITE: + _sslWantsTo = SslWantsTo::Write; + return rc; + + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + case SSL_ERROR_WANT_X509_LOOKUP: + // Unexpected. + return rc; + + case SSL_ERROR_SYSCALL: + if (errno != 0) + { + // Posix API error, let the caller handle. + return rc; + } + + // fallthrough + default: + { + // The error is comming from BIO. Find out what happened. + const long lastError = ERR_get_error(); + if (lastError == 0) + { + if (rc == 0) + { + // Socket closed. + return 0; + } + else if (rc == -1) + { + throw std::runtime_error("SSL Socket closed unexpectedly."); + } + else + { + throw std::runtime_error("SSL BIO reported error [" + std::to_string(rc) + "]."); + } + } + else + { + char buf[512]; + ERR_error_string_n(lastError, buf, sizeof(buf)); + throw std::runtime_error(buf); + } + } + break; + } + + return rc; + } + +private: SSL* _ssl; + SslWantsTo _sslWantsTo; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
