def write(bytes)
      loop do
        written = 0
        begin
          # unlike plain tcp sockets, ssl sockets don't support IO.select
          # properly.
          # Instead, timeouts happen on a per write basis, and we have to
          # catch exceptions from write_nonblock, and gradually build up
          # our write buffer.
          written += @ssl_socket.write_nonblock(bytes)
        rescue Errno::EFAULT => error
          raise error
        rescue OpenSSL::SSL::SSLError, Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable => error
          if error.is_a?(OpenSSL::SSL::SSLError) && error.message == 'write would block'
            if select_with_timeout(@ssl_socket, :write)
              retry
            else
              raise Errno::ETIMEDOUT
            end
          else
            raise error
          end
        end

        # Fast, common case.
        break if written == bytes.size

        # This takes advantage of the fact that most ruby implementations
        # have Copy-On-Write strings. Thusly why requesting a subrange
        # of data, we actually don't copy data because the new string
        # simply references a subrange of the original.
        bytes = bytes[written, bytes.size]
      end
    end
def write(bytes)
      loop do
        written = 0
        begin
          # unlike plain tcp sockets, ssl sockets don't support IO.select
          # properly.
          # Instead, timeouts happen on a per write basis, and we have to
          # catch exceptions from write_nonblock, and gradually build up
          # our write buffer.
          written += @ssl_socket.write_nonblock(bytes)
        rescue Errno::EFAULT => error
          raise error
        rescue OpenSSL::SSL::SSLError, Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable => error
          if error.is_a?(OpenSSL::SSL::SSLError) && error.message == 'write would block'
            if select_with_timeout(@ssl_socket, :write)
              retry
            else
              raise Errno::ETIMEDOUT
            end
          else
            raise error
          end
        end

        # Fast, common case.
        break if written == bytes.size

        # This takes advantage of the fact that most ruby implementations
        # have Copy-On-Write strings. Thusly why requesting a subrange
        # of data, we actually don't copy data because the new string
        # simply references a subrange of the original.
        bytes = bytes[written, bytes.size]
      end
    end
Writes bytes to the socket, possible with a timeout.

 @param bytes [String] the data that should be written to the socket.
 @raise [Errno::ETIMEDOUT] if the timeout is exceeded.
 @return [Integer] the number of bytes written.