code: def negotiate_sasl(transport, xmlstream,
                     sasl_providers,
                     negotiation_timeout,
                     jid, features):
      
  
      if not transport.get_extra_info("sslcontext"):
          transport = None
  
      last_auth_error = None
      for sasl_provider in sasl_providers:
          try:
              result = yield from sasl_provider.execute(
                  jid, features, xmlstream, transport)
          except ValueError as err:
              raise errors.StreamNegotiationFailure(
                  "invalid credentials: {}".format(err)
              ) from err
          except aiosasl.AuthenticationFailure as err:
              last_auth_error = err
              continue
  
          if result:
              features = yield from protocol.reset_stream_and_get_features(
                  xmlstream
              )
              break
      else:
          if last_auth_error:
              raise last_auth_error
          else:
              raise errors.SASLUnavailable("No common mechanisms")
  
      return features
docs: Perform SASL authentication on the given :class:`.protocol.XMLStream`
      `stream`. `transport` must be the :class:`asyncio.Transport` over which the
      `stream` runs. It is used to detect whether TLS is used and may be required
      by some SASL mechanisms.
  
      `sasl_providers` must be an iterable of :class:`SASLProvider` objects. They
      will be tried in iteration order to authenticate against the server. If one
      of the `sasl_providers` fails with a :class:`aiosasl.AuthenticationFailure`
      exception, the other providers are still tried; only if all providers fail,
      the last :class:`aiosasl.AuthenticationFailure` exception is re-raised.
  
      If no mechanism was able to authenticate but not due to authentication
      failures (other failures include no matching mechanism on the server side),
      :class:`aiosasl.SASLUnavailable` is raised.
  
      Return the :class:`.nonza.StreamFeatures` obtained after resetting the
      stream after successful SASL authentication.
  
      .. versionadded:: 0.6
  
      .. deprecated:: 0.10
  
          The `negotiation_timeout` argument is ignored. The timeout is
          controlled using the :attr:`~.XMLStream.deadtime_hard_limit` timeout
          of the stream.
  
          The argument will be removed in version 1.0. To prepare for this,
          please pass `jid` and `features` as keyword arguments.