diff options
author | Attila Molnar <attilamolnar@hush.com> | 2015-03-06 18:24:11 +0100 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2015-03-06 18:24:11 +0100 |
commit | e1e7ab0a18100d7e2cde0eb8d787f6ce1f958643 (patch) | |
tree | 4cd50754b3a7dc1994f33c171be1a4193af8075d /src/modules | |
parent | 30b78bc2f4f7b74574abfbb3a3c2dc04686d2e7d (diff) |
m_ssl_gnutls Set a vector push function on GnuTLS 2.12 and later
Setting a vector push function is recommended to reduce overhead during handshake
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/extra/m_ssl_gnutls.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index 12a776b06..a2bdb76ee 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -73,6 +73,7 @@ typedef gnutls_dh_params_t gnutls_dh_params; enum issl_status { ISSL_NONE, ISSL_HANDSHAKING, ISSL_HANDSHAKEN }; #if INSPIRCD_GNUTLS_HAS_VERSION(2, 12, 0) +#define INSPIRCD_GNUTLS_HAS_VECTOR_PUSH #define GNUTLS_NEW_CERT_CALLBACK_API typedef gnutls_retr2_st cert_cb_last_param_type; #else @@ -833,6 +834,42 @@ info_done_dealloc: return rv; } +#ifdef INSPIRCD_GNUTLS_HAS_VECTOR_PUSH + static ssize_t VectorPush(gnutls_transport_ptr_t transportptr, const giovec_t* iov, int iovcnt) + { + StreamSocket* sock = reinterpret_cast<StreamSocket*>(transportptr); +#ifdef _WIN32 + GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetIOHook()); +#endif + + if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK) + { +#ifdef _WIN32 + gnutls_transport_set_errno(session->sess, EAGAIN); +#else + errno = EAGAIN; +#endif + return -1; + } + + // Cast the giovec_t to iovec not to IOVector so the correct function is called on Windows + int ret = SocketEngine::WriteV(sock, reinterpret_cast<const iovec*>(iov), iovcnt); +#ifdef _WIN32 + // See the function above for more info about the usage of gnutls_transport_set_errno() on Windows + if (ret < 0) + gnutls_transport_set_errno(session->sess, SocketEngine::IgnoreError() ? EAGAIN : errno); +#endif + + int size = 0; + for (int i = 0; i < iovcnt; i++) + size += iov[i].iov_len; + + if (ret < size) + SocketEngine::ChangeEventMask(sock, FD_WRITE_WILL_BLOCK); + return ret; + } + +#else // INSPIRCD_GNUTLS_HAS_VECTOR_PUSH static ssize_t gnutls_push_wrapper(gnutls_transport_ptr_t session_wrap, const void* buffer, size_t size) { StreamSocket* sock = reinterpret_cast<StreamSocket*>(session_wrap); @@ -868,6 +905,7 @@ info_done_dealloc: SocketEngine::ChangeEventMask(sock, FD_WRITE_WILL_BLOCK); return rv; } +#endif // INSPIRCD_GNUTLS_HAS_VECTOR_PUSH public: GnuTLSIOHook(IOHookProvider* hookprov, StreamSocket* sock, inspircd_gnutls_session_init_flags_t flags, const reference<GnuTLS::Profile>& sslprofile) @@ -878,7 +916,11 @@ info_done_dealloc: { gnutls_init(&sess, flags); gnutls_transport_set_ptr(sess, reinterpret_cast<gnutls_transport_ptr_t>(sock)); +#ifdef INSPIRCD_GNUTLS_HAS_VECTOR_PUSH + gnutls_transport_set_vec_push_function(sess, VectorPush); +#else gnutls_transport_set_push_function(sess, gnutls_push_wrapper); +#endif gnutls_transport_set_pull_function(sess, gnutls_pull_wrapper); profile->SetupSession(sess); |