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); #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; } int rv = SocketEngine::Send(sock, reinterpret_cast<const char *>(buffer), size, 0); #ifdef _WIN32 if (rv < 0) { /* Windows doesn't use errno, but gnutls does, so check SocketEngine::IgnoreError() * and then set errno appropriately. * The gnutls library may also have a different errno variable than us, see * gnutls_transport_set_errno(3). */ gnutls_transport_set_errno(session->sess, SocketEngine::IgnoreError() ? EAGAIN : errno); } #endif if (rv < (int)size) SocketEngine::ChangeEventMask(sock, FD_WRITE_WILL_BLOCK); return rv; }
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; }