# File lib/excon/socket.rb, line 129
    def write(data)
      if @params[:nonblock]
        # We normally return from the return in the else block below, but
        # we guard that data is still something in case we get weird
        # values and String#[] returns nil. (This behavior has been observed
        # in the wild, so this is a simple defensive mechanism)
        while data
          begin
            # I wish that this API accepted a start position, then we wouldn't
            # have to slice data when there is a short write.
            written = @socket.write_nonblock(data)
          rescue OpenSSL::SSL::SSLError => error
            if error.message == 'write would block'
              if IO.select(nil, [@socket], nil, @params[:write_timeout])
                retry
              else
                raise(Excon::Errors::Timeout.new("write timeout reached"))
              end
            else
              raise(error)
            end
          rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable
            if IO.select(nil, [@socket], nil, @params[:write_timeout])
              retry
            else
              raise(Excon::Errors::Timeout.new("write timeout reached"))
            end
          else
            # Fast, common case.
            # The >= seems weird, why would it have written MORE than we
            # requested. But we're getting some weird behavior when @socket
            # is an OpenSSL socket, where it seems like it's saying it wrote
            # more (perhaps due to SSL packet overhead?).
            #
            # Pretty weird, but this is a simple defensive mechanism.
            return if written >= data.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.
            data = data[written, data.size]
          end
        end
      else
        begin
          Timeout.timeout(@params[:write_timeout]) do
            @socket.write(data)
          end
        rescue Timeout::Error
          Excon::Errors::Timeout.new('write timeout reached')
        end
      end
    end